Analysis of Samsung S22 and Apple iPhone 13

The Smartphone Market

The global smartphone market has experienced multiple market leaders over the past few years. The only two major brands that remained over the years were Apple and Samsung. Those two brands are compared regularly and are competing over the market share. While Samsung was the market leader in the first three quarters in 2021. In September 2021, Apple released its new iPhone model with the generation 13 and gained market share, taking over the market leader position. In February 2022, Samsung also released the new model in its Galaxy series. Those two phones are the flagships in the current smartphone market.

Source: IDC. (2022). Global smartphone market share from 4th quarter 2009 to 4th quarter 2021 (by vendor). Statista. Statista Inc.. Accessed: April 14, 2022.

Samsung Galaxy S22

The Samsung Galaxy S series is the high-end model produced and sold by Samsung, a South Korean multinational electronics company. The S series has 13 generations. Together with the Galaxy Z and Galaxy Note (discontinued) series, the S series serves as flagship models (Wikipedia, n.d.). Samsung S series uses the open source operating system Android (Samsung).

In February 2022 the model S22 was released in three variants: S22, S22 Plus (also: S22+) and S22 Ultra (Wikipedia, n.d.). It comes in the colours that are shown in the picture below, namely: phantom white, burgundy, phantom black and green (Samsung). Also the S22 Ultra variant comes with an so-called “S Pen” which lets the user write on their phone and can be recharged within the phone (Samsung).

Samsung advertises the S22 series with the following features:

  • "The phone that makes everyday epic

  • Nightography camera

  • A battery that lasts the day and beyond

  • Our fastest chip ever"

(Source: Samsung)

Picture Source

Apple iPhone 13

The Apple iPhone series is the only smartphone series produced and sold by Apple Inc, an US-American multinational technology company (Wikipedia).

The generation 13 was released in September 2021 in three variants: iPhone 13, iPhone 13 mini, iPhone 13 Pro, iPhone 13 Pro Max and iPhone SE. The regular variant and mini can be bought in the colours: green, pink, blue, midnight, starlight, red. The variants Pro and Pro Max are available in: alpine green, silver, gold, graphite, sierra blue. The iPhone SE is available in: midnight, starlight, red (Apple).

Apple advertises the iPhone Pro with the following features:

  • "A dramatically more powerful camera system.

  • A display so responsive, every interaction feels new again.

  • The world’s fastest smartphone chip.

  • Exceptional durability.

  • And a huge leap in battery life." (Samsung)

Picture Source

Comparison of Features

Samsung S22 Apple iPhone 13
Starting Price $799 $799
Screen size 6.1 inches (2340 x 1080) 6.1 inches (2532 x 1170)
Refresh rate 48Hz-120Hz adaptive 60Hz
CPU Snapdragon 8 Gen 1 (US); Exynos 2200 (K) A15 Bionic
RAM 8GB 4GB (based on teardowns)
Storage 128GB, 256GB 128GB, 256GB, 512GB
Rear cameras 50MP wide (f/1.8); 12MP ultrawide (f/2.2); 10MP telephoto (f/2.4) with 3x optical zoom 12MP main (f/1.6), 12MP ultrawide (f/2.4)
Front camera 10MP (f/2.2) 12MP (f/2.2)
Battery size 3,700 mAh 3,227 mAh (based on teardowns)
Battery life (Hrs:Mins) 7:51 10:33
Charging speeds 25W wired, 15W wireless 20W wired; 15W wireless
Size 5.7 x 2.8 x 0.3 inches 5.8 x 2.8 x 0.3 inches
Weight 5.9 ounces 6.14 ounces
Colors Black, white, green, pink gold Black, white, blue, pink, red, green

Source: https://www.tomsguide.com/face-off/samsung-galaxy-s22-vs-iphone-13

Objectives of our Research

  • Identification of the strengths and weaknesses of the competitors which can help to identify a gap in a market and enhancing the own business strategy.

  • Identification of suggestions to customers about the products based on other customers’ opinions

Methodology of our Research

Twitter Analysis

Data Extraction and Cleaning

Samsung S22

We decided to extract data from Twitter with the keywords “Samsung S22” and the hashtag “#samsungs22” from 31.03.2022 - 08.04.2022 as we do not have a premium license to get access to the full timeline of tweets on the TwitterAPI.

We excluded from our query the users ShopeeID, _arllee and all retweets for the keywords “Samsung S22” because there were multiple thousands of tweets about a competition to win a Samsung mobile phone which caused a lot of duplicated data.

As well, we identified nine users which were creating advertising spam and non-valuable tweets that we had to exclude: “whitestonedome”, “FromKorea5”, “dome_glass”, “Whitestone_DE”, “whitestone_UK”, “jp_whitestone”, “Whitestone__FR”, “WhitestoneJapan”, “WhitestoneEU”.

In total we could gather 3846 tweets.

Our initial data frame has 17 attributes. You can find the meaning of each of the attributes here on the Twitter Developer Platform.

In the following code we checked that the data.frame was correctly formatted:

Apple iPhone 13

We extracted data for the search terms “iPhone 13” excluding retweets and the hashtag “#iphone13” from the TwitterAPI. Similarly, to the Samsung S22 we had to exclude certain users which were advertising (“whitestonedome”, “FromKorea5”, “domeglassapple”) and competitions to win an iPhone when retweeting or copy-pasting a specific text (“Join the event to win an iPhone 13!”). Also, we had a high number of tweets which were randomly posting brand names, e.g. “rolex iphone” in one tweet.

In total we could gather 8369 tweets.

Our initial data frame has 17 attributes. You can find the meaning of each of the attributes here on the Twitter Developer Platform.

In the following code we checked that the data.frame was correctly formatted:

How Many Users Were Posting How Many Tweets in the Dataset?

While there were only 3846 tweets from users about the Samsung S22, there were 2.17 times more tweets about the Apple iPhone 13 during the period considered.

On 3 out of 9 days Samsung S22 had more tweets than iPhone 13. On the other days Apple exceeded the number of tweets extremely. Surprisingly, the number of tweets and users per day for the Samsung S22 remains constant while there are only a few tweets about the iPhone 13 in the first 3 days and a high volume of tweets from 3nd April until 7th April 2022. There was not only more tweets but also a larger group of users posting about iPhone 13. We could not identify a specific reason for this phenomenon because the last official Apple event was in March 2022 and not in the time period we tested.

There is no similar indicator from Google Trends or other sources. The search terms iPhone 13, Samsung S22, Apple and Samsung are relatively constant over time as you can see from the image below (Screenshot from Google Trends). It can be noted that Apple is more likely to be looked up than Samsung as well as the iPhone 13 is more popular on Google Search than Samsung S22. This gives us a first impression that the iPhone 13 model receives in general more attention.

There are more tweets than users which indicates that some users usually post more than one tweet. We calculated a ratio for this: avg_tweets_per_user = tweets per day / users per day.

It is interesting though there were less conversation about Apple in the first three days, there were statistically more people involved, so it seems to be a conversation between a smaller group of users. We see the same for Samsung S22 between 4th April to 6th April 2022.

Wordcloud

Data Preprocessing

We decided to preprocess the data based on the following steps:

  • All text was converted to lower case, e.g. Hello to hello.

  • All contractions were converted to the longer form, e.g. don’t to do not

  • All common internet slang was converted to formal English, e.g. TGIF to Thanks God it is Friday

  • Hashtags (#) were removed

  • Word elongation was replaced to the usual word form, e.g. heeeeey to hey

  • All non-ASCII characters were replaced with equivalent or removed, © to (C)

  • White space within the string is reduced to one white space

  • White space at the start and end of the string was removed

  • “RT”, implicating that its a retweet was removed

  • all links were removed based on the start of “http”

  • all @username were removed

  • punctuation were removed

  • stop words were removed based on the RegEx approach

Results

Samsung S22 users mentioned Samsung, Galaxy (which is the series of the S22) and Ultra (which is a specific model). The Ultra model is comparable to the iPhone 13 Pro.

Also iPhone, Pro, Max, Note & OnePlus are mentioned which are other comparable smartphones in the market.

Other words that are often mentioned belong to specifications that users talked about:

  • android, update, security

  • camera, pixel, video

  • features

  • mediatek

  • screen

  • amp

  • case

We can identify that Apple iPhone is mentioned in the variants Pro, Mini and Max. Pro seems to be the most important one, then Max and then the Mini.

As with the Samsung S22, also here it is mentioned with “Ultra”, “Galaxy” and “Samsung”.

The specifications of the phone that users talked about were:

  • pixel, camera

  • battery, amp

  • price

  • case

  • green

For iPhone 13, we can notice that some adjectives and verbs were mentioned a lot:

available, buy, win, free, still, now, good, better, best, like, will, get, want, need, can

We will identify topics further during our analysis using LDA Topic Modelling.

Insights

Both models are mentioned with their camera and pixel but only Samsung has the word “video” mentioned a lot. We identified in our pre-research about the phones that both companies advertise their smartphones based on the camera. None of both mentions about positive abilities in the video recording in their main advertisement.

For Samsung S22 users it seems to be important that a new update has been released. A new Android OS update for the series S22 has been released in April 2022 and updated security measurements and brought new features.

For Apple iPhone 13 it has been talked a lot about green. The generation 13 has been the first Flagship model to be produced in this colour, therefore it makes sense that people discuss about it.

Sentiment Analysis

Preprocessing Tweets

We need to preprocess data this time additionally with the following steps:

  • Emojis were replaced by the word form, e.g. Smiling emoji to smiling

  • Emoji Identifier were replaced by the word form, e.g. :-) to smiling

Sentiments in Tweets

The sentiment analysis

On the first look, sentiments are similar for both smartphone models and are commented on with highly positive sentiments. This means that on both models, users are generally speaking positively about their smartphone.

Samsung S22 has more trust and anticipation while iPhone 13 brings more joy to its users but also more sadness, surprise, fear and disgust.

Samsung S22 tweets were on average 10.4 words long while Apple iPhone 13 tweets had 9.9 words. The tweet with the maximum number of words was about iPhone 13 with 135 identified words. Samsung S22 with 34 words maximum words is quite shorter.

The sentimentr package in R estimates the sentiment polarity by sentence. The average sentiment for iPhone 13 was higher distributed with a range from -1.6 to +1.9 with its average at 0.26 while Samsung had a sentiment polarity from -1.1 to +1.6 with its average at 0.15. The higher variance within the data is identical to our findings from the plot “Relative Sentiment Score based on Tweets about Apple and Samsung” earlier. We can see from this that iPhone 13 users are in general more emotional - in a negative and positive direction - than Samsung S22 users. We assume that people are emotionally more dependent on their iPhone 13 than Samsung S22.

To see the sentiments per tweet, generate this HTML files:

Sentiment Terms

Now we want to extract the sentiment terms for both phones. What is liked by the users? What is not?

Samsung S22

Scandal is related to the GOS app that slowed Samsung phones down on purpose to save battery life without notifying the user about it.

Apple iPhone 13

Selecting by weightage

Word Correlation

Samsung S22

Selecting by weightage

Selecting by weightage

Apple iPhone 13

Selecting by weightage

Clustering

s_words_per_tweet <- data.frame(bg_df_s) %>%
  dplyr::mutate(tweet = row_number()) %>%
  unnest_tokens(output=bigrams, input=word_s, format= "text", token = "ngrams", n=1)

s_word_pairs <- s_words_per_tweet %>%
  pairwise_count(bigrams, tweet, sort = TRUE)
Warning: `distinct_()` was deprecated in dplyr 0.7.0.
Please use `distinct()` instead.
See vignette('programming') for more help
This warning is displayed once every 8 hours.
Call `lifecycle::last_warnings()` to see where this warning was generated.
s_word_cors <- s_words_per_tweet %>%
  group_by(bigrams) %>%
  filter(n() >= 20) %>%
  pairwise_cor(bigrams, tweet, sort = TRUE)

s_word_cors

s_word_cors %>%
  filter(item1 %in% c("android", "update", "security","camera", "pixel", "video","features", "mediatek","screen","amp","case")) %>%
  group_by(item1) %>%
  slice_max(correlation, n = 6) %>%
  ungroup() %>%
  mutate(item2 = reorder(item2, correlation)) %>%
  ggplot(aes(item2, correlation)) +
  geom_bar(stat = "identity") +
  facet_wrap(~ item1, scales = "free") +
  coord_flip()


s_word_cors %>%
  filter(item1 %in% c("available", "buy","win", "free","still","now", "good", "better", "best", "like","will", "get", "want", "need", "can")) %>%
  group_by(item1) %>%
  slice_max(correlation, n = 6) %>%
  ungroup() %>%
  mutate(item2 = reorder(item2, correlation)) %>%
  ggplot(aes(item2, correlation)) +
  geom_bar(stat = "identity") +
  facet_wrap(~ item1, scales = "free") +
  coord_flip()

s_words_per_tweet <- data.frame(bg_df_s) %>%
  dplyr::mutate(tweet = row_number()) %>%
  unnest_tokens(output=bigrams, input=word_s, format= "text", token = "ngrams", n=1)

s_word_pairs <- s_words_per_tweet %>%
  pairwise_count(bigrams, tweet, sort = TRUE)
Warning: `distinct_()` was deprecated in dplyr 0.7.0.
Please use `distinct()` instead.
See vignette('programming') for more help
This warning is displayed once every 8 hours.
Call `lifecycle::last_warnings()` to see where this warning was generated.
s_word_cors <- s_words_per_tweet %>%
  group_by(bigrams) %>%
  filter(n() >= 20) %>%
  pairwise_cor(bigrams, tweet, sort = TRUE)

s_word_cors

s_word_cors %>%
  filter(item1 %in% c("android", "update", "security","camera", "pixel", "video","features", "mediatek","screen","amp","case")) %>%
  group_by(item1) %>%
  slice_max(correlation, n = 6) %>%
  ungroup() %>%
  mutate(item2 = reorder(item2, correlation)) %>%
  ggplot(aes(item2, correlation)) +
  geom_bar(stat = "identity") +
  facet_wrap(~ item1, scales = "free") +
  coord_flip()


s_word_cors %>%
  filter(item1 %in% c("available", "buy","win", "free","still","now", "good", "better", "best", "like","will", "get", "want", "need", "can")) %>%
  group_by(item1) %>%
  slice_max(correlation, n = 6) %>%
  ungroup() %>%
  mutate(item2 = reorder(item2, correlation)) %>%
  ggplot(aes(item2, correlation)) +
  geom_bar(stat = "identity") +
  facet_wrap(~ item1, scales = "free") +
  coord_flip()

LDA Topic Modelling

Samsung S22

The topics about “seri”, “now”, “camera”, “update” relates to the S22 Ultra’s April patch that introduced many camera-related features.

Apple iPhone 13

$CTM
      Topic 1 Topic 2   Topic 3 Topic 4 Topic 5   Topic 6 Topic 7   Topic 8 Topic 9  Topic 10
 [1,] "mini"  "case"    "use"   "just"  "new"     "phone" "phone"   "get"   "phone"  "phone" 
 [2,] "phone" "new"     "get"   "green" "phone"   "new"   "just"    "case"  "new"    "case"  
 [3,] "just"  "get"     "green" "get"   "case"    "get"   "like"    "can"   "just"   "camera"
 [4,] "case"  "mini"    "case"  "use"   "use"     "buy"   "case"    "got"   "case"   "like"  
 [5,] "use"   "green"   "buy"   "buy"   "get"     "now"   "camera"  "want"  "get"    "will"  
 [6,] "get"   "one"     "want"  "will"  "buy"     "want"  "buy"     "will"  "use"    "want"  
 [7,] "one"   "now"     "phone" "now"   "batteri" "use"   "get"     "win"   "green"  "mini"  
 [8,] "can"   "batteri" "got"   "case"  "can"     "like"  "got"     "need"  "camera" "amp"   
 [9,] "like"  "like"    "amp"   "can"   "want"    "one"   "batteri" "give"  "can"    "win"   
[10,] "new"   "want"    "will"  "like"  "now"     "got"   "amp"     "day"   "will"   "can"   

$VEM
      Topic 1 Topic 2 Topic 3 Topic 4  Topic 5 Topic 6  Topic 7  Topic 8 Topic 9 Topic 10
 [1,] "get"   "green" "green" "new"    "phone" "phone"  "phone"  "like"  "new"   "new"   
 [2,] "phone" "case"  "case"  "use"    "get"   "get"    "new"    "case"  "green" "use"   
 [3,] "case"  "want"  "new"   "camera" "want"  "case"   "want"   "phone" "mini"  "phone" 
 [4,] "just"  "got"   "use"   "buy"    "can"   "buy"    "just"   "want"  "like"  "mini"  
 [5,] "like"  "just"  "can"   "want"   "buy"   "can"    "camera" "one"   "amp"   "camera"
 [6,] "one"   "watch" "just"  "case"   "mini"  "mini"   "case"   "just"  "now"   "like"  
 [7,] "price" "good"  "got"   "can"    "new"   "camera" "amp"    "give"  "give"  "just"  
 [8,] "can"   "best"  "now"   "will"   "will"  "got"    "will"   "mini"  "plus"  "case"  
 [9,] "now"   "can"   "plus"  "one"    "got"   "one"    "use"    "new"   "know"  "price" 
[10,] "got"   "use"   "need"  "win"    "one"   "new"    "now"    "look"  "win"   "can"   

$VEM_Fixed
      Topic 1 Topic 2 Topic 3 Topic 4  Topic 5 Topic 6  Topic 7  Topic 8 Topic 9 Topic 10
 [1,] "get"   "green" "green" "new"    "phone" "phone"  "phone"  "like"  "new"   "new"   
 [2,] "phone" "case"  "case"  "use"    "get"   "get"    "new"    "case"  "green" "use"   
 [3,] "case"  "want"  "new"   "camera" "want"  "case"   "want"   "phone" "mini"  "phone" 
 [4,] "just"  "got"   "use"   "buy"    "can"   "buy"    "just"   "want"  "like"  "camera"
 [5,] "like"  "just"  "can"   "want"   "buy"   "can"    "camera" "one"   "amp"   "mini"  
 [6,] "one"   "watch" "just"  "case"   "mini"  "mini"   "case"   "just"  "now"   "like"  
 [7,] "price" "good"  "got"   "can"    "new"   "camera" "amp"    "give"  "give"  "just"  
 [8,] "can"   "best"  "now"   "will"   "will"  "got"    "will"   "mini"  "know"  "case"  
 [9,] "now"   "can"   "plus"  "one"    "got"   "one"    "use"    "new"   "plus"  "price" 
[10,] "got"   "use"   "need"  "win"    "one"   "new"    "now"    "avail" "win"   "can"   

$Gibbs
      Topic 1   Topic 2    Topic 3      Topic 4   Topic 5   Topic 6 Topic 7   Topic 8   Topic 9    Topic 10 
 [1,] "septemb" "mode"     "prank"      "cat"     "wall"    "phone" "expect"  "regist"  "plug"     "die"    
 [2,] "lock"    "care"     "jailbreak"  "rate"    "special" "case"  "auto"    "\"cute"  "headphon" "matter" 
 [3,] "annoy"   "\"got"    "deliv"      "bot"     "opinion" "get"   "pixel"   "eidi"    "notif"    "includ" 
 [4,] "seat"    "circl"    "imag"       "channel" "foldabl" "new"   "compani" "prize"   "question" "delet"  
 [5,] "success" "min"      "resist"     "cuti"    "side"    "just"  "comput"  "\"buy"   "wit"      "email"  
 [6,] "\"peopl" "total"    "carri"      "friday"  "cost"    "use"   "freez"   "current" "anim"     "kinda"  
 [7,] "plate"   "bar"      "content"    "sinc"    "free"    "can"   "magnet"  "factori" "concert"  "outsid" 
 [8,] "portabl" "friend"   "fraud"      "address" "open"    "buy"   "regular" "fund"    "care"     "token"  
 [9,] "proof"   "internet" "girlfriend" "compact" "rang"    "want"  "remind"  "icon"    "despit"   "fav"    
[10,] "school"  "kept"     "may"        "advanc"  "trash"   "green" "past"    "overh"   "exact"    "mini\","

      CTM.1       VEM.1 VEM_Fixed.1     Gibbs.1 
         10           1           1           6 

Amazon Review Analysis

For further analysis, we have decided to analyse the Amazon product reviews for both the phones in order to understand if the sentiments of customers on Twitter and Amazon were matching or not.

To do this, the first step was to collect the data. We faced a similar situation for collecting the data, Samsung S22 had very few reviews and the iPhone 13 had a large amount of reviews. So, to collect more data, we used Amazon reviews from different country websites like UK, India, USA and Australia. Specifically, English reviews were selected to proceed with the analysis.

The following R code was implemented to collect data from different Amazon websites. (<https://martinctc.github.io/blog/vignette-scraping-amazon-reviews-in-r/>)

Data Scraping from Amazon

# #Scraping Product Reviews from Amazon
# 
# #import libraries
# library(rvest)
# library(stringr)
# library(xml2)
# library(tidyverse)
# 
# 
# scrape_amazon <- function(ASIN, page_num){
#   
#   #amazon_uk
#   #url_reviews <- paste0("https://www.amazon.co.uk/product-reviews/",ASIN,"/?pageNumber=",page_num)
#   #amazon.com
#   #url_reviews <- paste0("https://www.amazon.com/product-reviews/",ASIN,"/?pageNumber=",page_num)
#   #amazon.in
#   #url_reviews <- paste0("https://www.amazon.in/product-reviews/",ASIN,"/?pageNumber=",page_num)
#   
#   #amazon.com.au
#   url_reviews <- paste0("https://www.amazon.com.au/product-reviews/",ASIN,"/?pageNumber=",page_num)
#   
#   doc <- read_html(url_reviews) # Assign results to `doc`
#   
#   # Review Title
#   doc %>% 
#     html_nodes("[class='a-size-base a-link-normal review-title a-color-base review-title-content a-text-bold']") %>%
#     html_text() -> review_title1
#   
#   review_title <- str_squish(review_title1)
#   
#   # Review Text
#   doc %>% 
#     html_nodes("[class='a-size-base review-text review-text-content']") %>%
#     html_text() -> review_text1
#   
#   review_text <- str_squish(review_text1)
#   
#   # Number of stars in review
#   doc %>%
#     html_nodes("[data-hook='review-star-rating']") %>%
#     html_text() -> review_star1
#   
#   review_star <- str_squish(review_star1)
#   
#   # Date 
#   
#   doc %>%
#     html_nodes("[data-hook='review-date']") %>%
#     html_text() -> review_date1
#   review_date <- str_squish(review_date1)
#   
#   # Return a tibble
#  tibble(review_title,
#          review_text,
#          review_star,
#          review_date,
#          page = page_num) %>% return()
# }
# 
# 
# ASIN <- "B09MW17JQY" # Specify ASIN
# page_range <- 1 # Let's say we want to scrape pages 1 to 10
# 
# match_key <- tibble(n = page_range,
#                     key = sample(page_range,length(page_range)))
# 
# lapply(page_range, function(i){
#   j <- match_key[match_key$n==i,]$key
#   
#   message("Getting page ",i, " of ",length(page_range), "; Actual: page ",j) # Progress bar
#   
#   Sys.sleep(3) # Take a three second break
#   
#   if((i %% 3) == 0){ # After every three scrapes... take another two second break
#     
#     message("Taking a break...") # Prints a 'taking a break' message on your console
#     
#     Sys.sleep(2) # Take an additional two second break
#   }
#   scrape_amazon(ASIN = ASIN, page_num = j) # Scrape
# }) -> output_list
# 
# 
# write.csv(output_list,"C:\\Users\\Shruthi\\OneDrive\\Documents\\Semester 2\\Social Media Analytics\\Group Assignment\\Samsung_Australia.csv",row.names = FALSE)

Data Input

[1] 110   5
 review_title       review_text        review_star        review_date             page       
 Length:110         Length:110         Length:110         Length:110         Min.   : 1.000  
 Class :character   Class :character   Class :character   Class :character   1st Qu.: 2.000  
 Mode  :character   Mode  :character   Mode  :character   Mode  :character   Median : 5.000  
                                                                             Mean   : 5.091  
                                                                             3rd Qu.: 8.000  
                                                                             Max.   :10.000  
[1] 507   5
 review_title       review_text        review_star        review_date             page      
 Length:507         Length:507         Length:507         Length:507         Min.   : 1.00  
 Class :character   Class :character   Class :character   Class :character   1st Qu.: 6.00  
 Mode  :character   Mode  :character   Mode  :character   Mode  :character   Median :15.00  
                                                                             Mean   :17.09  
                                                                             3rd Qu.:28.00  
                                                                             Max.   :40.00  

Data Preprocessing

shifted.words <- iphone.reviews.text %>%
  unnest_tokens(bigram, review_text, token = "ngrams", n = 2)%>%
  dplyr::count(bigram, sort = TRUE) %>%
  separate(bigram, c("word1", "word2"), sep = " ")%>%
  filter(word1 %in% negation.words & !word2 %in% stop_words$word)%>%
  inner_join(get_sentiments("bing"), by = c(word2 = "word"))%>%
  mutate(sentiment = ifelse(sentiment == "positive", 1, -1)) %>%
  mutate(score = sentiment * n) %>%
  mutate(word2 = reorder(word2, score))

shifted.words

iphone.reviews.text <- mgsub(iphone.reviews.text$review_text, negated.phrases, synonyms) %>%
  dplyr::as_data_frame() %>%
  rename(review_text = value)

iphone.reviews.text

Wordcloud

Sentiment Analysis

# if you want to ignore words that are frequent but doesn't help, add them to this list. ###Ignore the words
ignore.words <- data_frame(word = c("iphone", "phone","apple", "13"))

# create the words freq table
word.freq.table_a<- iphone.reviews.text %>% 
  unnest_tokens(word, review_text) %>%
  anti_join(stop_words) %>%
  anti_join(ignore.words) %>%
  dplyr::count(word, sort = TRUE)
Joining, by = "word"
Joining, by = "word"
word.freq.table_a

# Plotting a Wordcloud
word.freq.table_a %>% 
  filter(n>8) %>%
  with(wordcloud(word, n,
                 scale = c(5,0.3),
                 colors = brewer.pal(8, "Dark2")))

#Samsung
# rescale the range to 5 star range.
bing.mean.score_s<-rescale(bing.mean.score_s$mean, to = c(1,5), from = c(-1,1))

# Afinn scores are from -5 to 5.
afinn.mean.score_s <- word.freq.table_s %>% 
  inner_join(get_sentiments("afinn"))%>%
  summarise(Samsung_mean = mean(value))

# rescale the range to 5 star range.
afinn.mean.score_s<-rescale(afinn.mean.score_s$Samsung_mean, to = c(1,5), from = c(-5,5))

#Apple
# rescale the range to 5 star range.
bing.mean.score_a<-rescale(bing.mean.score_a$mean, to = c(1,5), from = c(-1,1))

# Afinn scores are from -5 to 5.
afinn.mean.score_a <- word.freq.table_a %>% 
  inner_join(get_sentiments("afinn"))%>%
  summarise(Apple_mean = mean(value))

# rescale the range to 5 star range.
afinn.mean.score_a<-rescale(afinn.mean.score_a$Apple_mean, to = c(1,5), from = c(-5,5))
afinn.mean.score_a

data.table(afinn.mean.score_s, afinn.mean.score_a)

Word Correlation

# Most common Positive and Negative words using Bing
iphone.reviews.text %>% 
  unnest_tokens(word, review_text) %>%
  anti_join(stop_words) %>%
  anti_join(ignore.words) %>%
  inner_join(get_sentiments("bing")) %>%
  dplyr::count(word, sentiment, sort = TRUE) %>%
  filter(n > 2) %>%
  mutate(word = reorder(word, n)) %>%
  mutate(percent = round(n/sum(n), 3)) %>%
  ggplot(aes(x = word, y = percent, fill = sentiment, label = percent)) +
  geom_col(show.legend = FALSE) +
  facet_wrap(~sentiment, scales = "free_y") +
  geom_text(aes(y = 0.7*percent)) +
  labs(title = "iPhone 13 Word Polarity (bing)") +
  coord_flip() + 
  theme_bw() +
  theme(plot.title = element_text(hjust = 0.5))
Joining, by = "word"
Joining, by = "word"
Joining, by = "word"

# Correlation Terms
# The correlation of appearing together in a review
apple.correlation.terms <- iphone.reviews.text %>%
  mutate(review = row_number()) %>%
  unnest_tokens(word, review_text) %>%
  filter(!word %in% stop_words$word) %>%
  group_by(word) %>%
  filter(n() >= 5)%>%
  pairwise_cor(word, review, sort = TRUE)
apple.correlation.terms

library(ggraph)
library(igraph)
apple.correlation.terms %>%
  filter(correlation >= 0.50) %>%
  graph_from_data_frame() %>%
  ggraph(layout = "igraph", algorithm = "kk") +
  geom_edge_link(aes(alpha = correlation), 
                 show.legend = FALSE)+
  geom_node_point(color = "lightblue", size = 2) +
  geom_node_text(aes(label = name), repel = TRUE) +
  theme_void()+
  ggtitle("Correlation of terms in Apple iPhone 13 Reviews")
#Samsung
# rescale the range to 5 star range.
bing.mean.score_s<-rescale(bing.mean.score_s$mean, to = c(1,5), from = c(-1,1))
Warning: Unknown or uninitialised column: `mean`.
# Afinn scores are from -5 to 5.
afinn.mean.score_s <- word.freq.table_s %>% 
  inner_join(get_sentiments("afinn"))%>%
  summarise(Samsung_mean = mean(value))
Joining, by = "word"
# rescale the range to 5 star range.
afinn.mean.score_s<-rescale(afinn.mean.score_s$Samsung_mean, to = c(1,5), from = c(-5,5))

#Apple
# rescale the range to 5 star range.
bing.mean.score_a<-rescale(bing.mean.score_a$mean, to = c(1,5), from = c(-1,1))
Warning: Unknown or uninitialised column: `mean`.
# Afinn scores are from -5 to 5.
afinn.mean.score_a <- word.freq.table_a %>% 
  inner_join(get_sentiments("afinn"))%>%
  summarise(Apple_mean = mean(value))
Joining, by = "word"
# rescale the range to 5 star range.
afinn.mean.score_a<-rescale(afinn.mean.score_a$Apple_mean, to = c(1,5), from = c(-5,5))
afinn.mean.score_a
[1] 3.117557
data.table(afinn.mean.score_s, afinn.mean.score_a)
shifted.words <- samsung.reviews.text %>%
  unnest_tokens(bigram, review_text, token = "ngrams", n = 2)%>%
  dplyr::count(bigram, sort = TRUE) %>%
  separate(bigram, c("word1", "word2"), sep = " ")%>%
  filter(word1 %in% negation.words & !word2 %in% stop_words$word)%>%
  inner_join(get_sentiments("bing"), by = c(word2 = "word"))%>%
  mutate(sentiment = ifelse(sentiment == "positive", 1, -1)) %>%
  mutate(score = sentiment * n) %>%
  mutate(word2 = reorder(word2, score))

shifted.words

# Pick the most effective sentiment shifters
negated.phrases <- c("not worth", 
                     "not noise",
                     "no issues",
                     "no complaints",
                     "not disappoint",
                     "not disappointed",
                     "not cheap",
                     "no regrets"
                     
)

# Find synonyms for the phrases above to replace
synonyms <- c("expensive",
              "functional",
              "cool",
              "satisfied",
              "satisfied",
              "satisfied",
              "expensive",
              "satisfied"
)
library(textclean)
# Replace the negations with their synonyms.
samsung.reviews.text <- mgsub(samsung.reviews.text$review_text, negated.phrases, synonyms) %>%
  dplyr::as_data_frame() %>%
  rename(review_text = value)

samsung.reviews.text
NA
shifted.words <- iphone.reviews.text %>%
  unnest_tokens(bigram, review_text, token = "ngrams", n = 2)%>%
  dplyr::count(bigram, sort = TRUE) %>%
  separate(bigram, c("word1", "word2"), sep = " ")%>%
  filter(word1 %in% negation.words & !word2 %in% stop_words$word)%>%
  inner_join(get_sentiments("bing"), by = c(word2 = "word"))%>%
  mutate(sentiment = ifelse(sentiment == "positive", 1, -1)) %>%
  mutate(score = sentiment * n) %>%
  mutate(word2 = reorder(word2, score))

shifted.words

iphone.reviews.text <- mgsub(iphone.reviews.text$review_text, negated.phrases, synonyms) %>%
  dplyr::as_data_frame() %>%
  rename(review_text = value)

iphone.reviews.text
# now we find the centrality measures of the network
# degree:the number of its adjacent edges (measure of direct influence)
deg_a <- degree(bigrams.network_a, mode = "all")

#K-core decomposition allows us to identify the core and the periphery of the network. A k-core is a maximal subnet of a network such that all nodes have at least degree K.
core_a <- coreness(bigrams.network_a, mode = "all")

# betweenness measures brokerage or gatekeeping potential. It is (approximately) the number of shortest paths between nodes that pass through a particular node.
betw_a <- betweenness(bigrams.network_a)

#Eigenvector centrality is a measure of being well-connected connected to the well-connected. First eigenvector of the graph adjacency matrix. Only works with undirected networks.
eigen_a <- eigen_centrality(bigrams.network_a, directed = TRUE)
members_a <- cluster_walktrap(bigrams.network_a)

library(igraph)
bigrams.network_a <- simplify(bigrams.network_a
                            #remove.multiple = FALSE, #error occured ?
                            #remove.loops = TRUE)
)
V(bigrams.network_a)$color <- members_a$membership+1

# Using "Coreness" as size
# Coreness -> mean (average distance to all the other nodes, diffusion of information)
plot(bigrams.network_a,
     layout = layout_with_fr,
     vertex.label.color = "black",
     vertex.label.cex = 0.9,
     vertex.label.dist = 0,
     vertex.frame.color = 0,
     vertex.size = core_a*10, 
     edge.arrow.size = 0.01,
     edge.curved = 0.7,
     edge.color = "gray",
     main = "Bigram Communities (iPhone 13)"
)
mtext("Coreness")

# Using "Degree" as size
# degree=mode (number of edges of the node, in-degree:prestige

plot(bigrams.network_a,
     layout = layout_with_fr,
     vertex.label.color = "black",
     vertex.label.cex = 0.9,
     vertex.label.dist = 0,
     vertex.frame.color = 0,
     vertex.size = deg_a, 
     edge.arrow.size = 0.01,
     edge.curved = 0.7,
     edge.color = "gray",
     main = "Bigram Communities (iPhone 13)"
)
mtext("Degree")

# Using "Eigenvector Centrality" as size
# centrality (the most connected words)
plot(bigrams.network_a,
     layout = layout_with_fr,
     vertex.label.color = "black",
     vertex.label.cex = 0.8,
     vertex.label.dist = 0,
     vertex.size = eigen_a$vector*20, 
     edge.arrow.size = 0.01,
     edge.curved = 0.7,
     edge.color = "black",
     main = "Bigram Communities (iPhone 13)"
)
mtext("Eigenvector Centrality")

# Using "Betweenness" as size
#Betweenness -> median (weighted # of paths going through the node)
plot(bigrams.network_a,
     layout = layout_with_fr,
     vertex.label.color = "black",
     vertex.label.cex = 0.8,
     vertex.label.dist = 0,
     vertex.size = betw_a, 
     edge.arrow.size = 0.01,
     edge.curved = 0.7,
     edge.color = "lightgrey",
     main = "Bigram Communities (iPhone 13)"
)
mtext("Betweenness")
LS0tCnRpdGxlOiAiQnJhbmQgQW5hbHlzaXMgb2YgU2Ftc3VuZyBTMjIgYW5kIEFwcGxlIGlQaG9uZSAxMyBDb21wYXJpc29uIgphdXRob3JzOiBNb2hpdCBSYXRob2QsIFNocnV0aGkgWWFtYWphbGEsIFpoaXl1IFd1LCBNYXJpZSBMaXNhbm5lIFNjaMO8cm1hbm4Kb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKLS0tCgojIEFuYWx5c2lzIG9mIFNhbXN1bmcgUzIyIGFuZCBBcHBsZSBpUGhvbmUgMTMKCiMjIFRoZSBTbWFydHBob25lIE1hcmtldAoKVGhlIGdsb2JhbCBzbWFydHBob25lIG1hcmtldCBoYXMgZXhwZXJpZW5jZWQgbXVsdGlwbGUgbWFya2V0IGxlYWRlcnMgb3ZlciB0aGUgcGFzdCBmZXcgeWVhcnMuIFRoZSBvbmx5IHR3byBtYWpvciBicmFuZHMgdGhhdCByZW1haW5lZCBvdmVyIHRoZSB5ZWFycyB3ZXJlIEFwcGxlIGFuZCBTYW1zdW5nLiBUaG9zZSB0d28gYnJhbmRzIGFyZSBjb21wYXJlZCByZWd1bGFybHkgYW5kIGFyZSBjb21wZXRpbmcgb3ZlciB0aGUgbWFya2V0IHNoYXJlLiBXaGlsZSBTYW1zdW5nIHdhcyB0aGUgbWFya2V0IGxlYWRlciBpbiB0aGUgZmlyc3QgdGhyZWUgcXVhcnRlcnMgaW4gMjAyMS4gSW4gU2VwdGVtYmVyIDIwMjEsIEFwcGxlIHJlbGVhc2VkIGl0cyBuZXcgaVBob25lIG1vZGVsIHdpdGggdGhlIGdlbmVyYXRpb24gMTMgYW5kIGdhaW5lZCBtYXJrZXQgc2hhcmUsIHRha2luZyBvdmVyIHRoZSBtYXJrZXQgbGVhZGVyIHBvc2l0aW9uLiBJbiBGZWJydWFyeSAyMDIyLCBTYW1zdW5nIGFsc28gcmVsZWFzZWQgdGhlIG5ldyBtb2RlbCBpbiBpdHMgR2FsYXh5IHNlcmllcy4gVGhvc2UgdHdvIHBob25lcyBhcmUgdGhlIGZsYWdzaGlwcyBpbiB0aGUgY3VycmVudCBzbWFydHBob25lIG1hcmtldC4KCiFbXShpbWFnZXMvcGFzdGUtM0M2NThEMDYucG5nKQoKU291cmNlOiBbSURDLiAoMjAyMikuwqBHbG9iYWwgc21hcnRwaG9uZSBtYXJrZXQgc2hhcmUgZnJvbSA0dGggcXVhcnRlciAyMDA5IHRvIDR0aCBxdWFydGVyIDIwMjEgKGJ5IHZlbmRvcikuwqBTdGF0aXN0YS4gU3RhdGlzdGEgSW5jLi5dKGh0dHBzOi8vd3d3LnN0YXRpc3RhLmNvbS9zdGF0aXN0aWNzLzI3MTQ5Ni9nbG9iYWwtbWFya2V0LXNoYXJlLWhlbGQtYnktc21hcnRwaG9uZS12ZW5kb3JzLXNpbmNlLTR0aC1xdWFydGVyLTIwMDkvKSBBY2Nlc3NlZDogQXByaWwgMTQsIDIwMjIuCgojIyBTYW1zdW5nIEdhbGF4eSBTMjIKClRoZSBTYW1zdW5nIEdhbGF4eSBTIHNlcmllcyBpcyB0aGUgaGlnaC1lbmQgbW9kZWwgcHJvZHVjZWQgYW5kIHNvbGQgYnkgU2Ftc3VuZywgYSBTb3V0aCBLb3JlYW4gbXVsdGluYXRpb25hbCBlbGVjdHJvbmljcyBjb21wYW55LiBUaGUgUyBzZXJpZXMgaGFzIDEzIGdlbmVyYXRpb25zLiBUb2dldGhlciB3aXRoIHRoZSBHYWxheHkgWiBhbmQgR2FsYXh5IE5vdGUgKGRpc2NvbnRpbnVlZCkgc2VyaWVzLCB0aGUgUyBzZXJpZXMgc2VydmVzIGFzIGZsYWdzaGlwIG1vZGVscyAoW1dpa2lwZWRpYSwgbi5kLildKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1NhbXN1bmdfR2FsYXh5X1Nfc2VyaWVzICJXaWtpcGVkaWEgU2Ftc3VuZyBHYWxheHkgUyBzZXJpZXMiKS4gU2Ftc3VuZyBTIHNlcmllcyB1c2VzIHRoZSBvcGVuIHNvdXJjZSBvcGVyYXRpbmcgc3lzdGVtIEFuZHJvaWQgKFtTYW1zdW5nXShodHRwczovL3d3dy5zYW1zdW5nLmNvbS9pZS9zbWFydHBob25lcy9nYWxheHktczIyLXVsdHJhLykpLgoKSW4gRmVicnVhcnkgMjAyMiB0aGUgbW9kZWwgUzIyIHdhcyByZWxlYXNlZCBpbiB0aHJlZSB2YXJpYW50czogUzIyLCBTMjIgUGx1cyAoYWxzbzogUzIyKykgYW5kIFMyMiBVbHRyYSAoW1dpa2lwZWRpYSwgbi5kLildKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1NhbXN1bmdfR2FsYXh5X1Nfc2VyaWVzICJXaWtpcGVkaWEgU2Ftc3VuZyBHYWxheHkgUyBzZXJpZXMiKS4gSXQgY29tZXMgaW4gdGhlIGNvbG91cnMgdGhhdCBhcmUgc2hvd24gaW4gdGhlIHBpY3R1cmUgYmVsb3csIG5hbWVseTogcGhhbnRvbSB3aGl0ZSwgYnVyZ3VuZHksIHBoYW50b20gYmxhY2sgYW5kIGdyZWVuIChbU2Ftc3VuZ10oaHR0cHM6Ly93d3cuc2Ftc3VuZy5jb20vaWUvc21hcnRwaG9uZXMvZ2FsYXh5LXMyMi11bHRyYS8pKS4gQWxzbyB0aGUgUzIyIFVsdHJhIHZhcmlhbnQgY29tZXMgd2l0aCBhbiBzby1jYWxsZWQgIlMgUGVuIiB3aGljaCBsZXRzIHRoZSB1c2VyIHdyaXRlIG9uIHRoZWlyIHBob25lIGFuZCBjYW4gYmUgcmVjaGFyZ2VkIHdpdGhpbiB0aGUgcGhvbmUgKFtTYW1zdW5nXShodHRwczovL3d3dy5zYW1zdW5nLmNvbS9pZS9zbWFydHBob25lcy9nYWxheHktczIyLXVsdHJhLykpLgoKU2Ftc3VuZyBhZHZlcnRpc2VzIHRoZSBTMjIgc2VyaWVzIHdpdGggdGhlIGZvbGxvd2luZyBmZWF0dXJlczoKCi0gICAiVGhlIHBob25lIHRoYXQgbWFrZXMgZXZlcnlkYXkgZXBpYwoKLSAgIE5pZ2h0b2dyYXBoeSBjYW1lcmEKCi0gICBBIGJhdHRlcnkgdGhhdCBsYXN0cyB0aGUgZGF5IGFuZCBiZXlvbmQKCi0gICBPdXIgZmFzdGVzdCBjaGlwIGV2ZXIiCgooU291cmNlOiBbU2Ftc3VuZ10oaHR0cHM6Ly93d3cuc2Ftc3VuZy5jb20vaWUvc21hcnRwaG9uZXMvZ2FsYXh5LXMyMi8pKQoKWyFbXShodHRwczovL2ltZy5nbG9iYWwubmV3cy5zYW1zdW5nLmNvbS9nbG9iYWwvd3AtY29udGVudC91cGxvYWRzLzIwMjIvMDIvR2FsYXh5LVMyMi1TMjItcHJfbWFpbjEuanBnICJTYW1zdW5nIFMyMiIpe3dpZHRoPSI3MDcifV0oaHR0cHM6Ly9pbWcuZ2xvYmFsLm5ld3Muc2Ftc3VuZy5jb20vZ2xvYmFsL3dwLWNvbnRlbnQvdXBsb2Fkcy8yMDIyLzAyL0dhbGF4eS1TMjItUzIyLXByX21haW4xLmpwZykKCltQaWN0dXJlIFNvdXJjZV0oaHR0cHM6Ly9pbWcuZ2xvYmFsLm5ld3Muc2Ftc3VuZy5jb20vZ2xvYmFsL3dwLWNvbnRlbnQvdXBsb2Fkcy8yMDIyLzAyL0dhbGF4eS1TMjItUzIyLXByX21haW4xLmpwZykKCiMjIEFwcGxlIGlQaG9uZSAxMwoKVGhlIEFwcGxlIGlQaG9uZSBzZXJpZXMgaXMgdGhlIG9ubHkgc21hcnRwaG9uZSBzZXJpZXMgcHJvZHVjZWQgYW5kIHNvbGQgYnkgQXBwbGUgSW5jLCBhbiBVUy1BbWVyaWNhbiBtdWx0aW5hdGlvbmFsIHRlY2hub2xvZ3kgY29tcGFueSAoW1dpa2lwZWRpYV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSVBob25lKSkuCgpUaGUgZ2VuZXJhdGlvbiAxMyB3YXMgcmVsZWFzZWQgaW4gU2VwdGVtYmVyIDIwMjEgaW4gdGhyZWUgdmFyaWFudHM6IGlQaG9uZSAxMywgaVBob25lIDEzIG1pbmksIGlQaG9uZSAxMyBQcm8sIGlQaG9uZSAxMyBQcm8gTWF4IGFuZCBpUGhvbmUgU0UuIFRoZSByZWd1bGFyIHZhcmlhbnQgYW5kIG1pbmkgY2FuIGJlIGJvdWdodCBpbiB0aGUgY29sb3VyczogZ3JlZW4sIHBpbmssIGJsdWUsIG1pZG5pZ2h0LCBzdGFybGlnaHQsIHJlZC4gVGhlIHZhcmlhbnRzIFBybyBhbmQgUHJvIE1heCBhcmUgYXZhaWxhYmxlIGluOiBhbHBpbmUgZ3JlZW4sIHNpbHZlciwgZ29sZCwgZ3JhcGhpdGUsIHNpZXJyYSBibHVlLiBUaGUgaVBob25lIFNFIGlzIGF2YWlsYWJsZSBpbjogbWlkbmlnaHQsIHN0YXJsaWdodCwgcmVkIChbQXBwbGVdKGh0dHBzOi8vd3d3LmFwcGxlLmNvbS9pcGhvbmUvKSkuCgpBcHBsZSBhZHZlcnRpc2VzIHRoZSBpUGhvbmUgUHJvIHdpdGggdGhlIGZvbGxvd2luZyBmZWF0dXJlczoKCi0gICAiQSBkcmFtYXRpY2FsbHkgbW9yZSBwb3dlcmZ1bCBjYW1lcmEgc3lzdGVtLgoKLSAgIEEgZGlzcGxheSBzbyByZXNwb25zaXZlLCBldmVyeSBpbnRlcmFjdGlvbiBmZWVscyBuZXcgYWdhaW4uCgotICAgVGhlIHdvcmxkJ3MgZmFzdGVzdCBzbWFydHBob25lIGNoaXAuCgotICAgRXhjZXB0aW9uYWwgZHVyYWJpbGl0eS4KCi0gICBBbmQgYSBodWdlIGxlYXAgaW4gYmF0dGVyeSBsaWZlLiIgKFtTYW1zdW5nXShodHRwczovL3d3dy5hcHBsZS5jb20vaXBob25lLTEzLXByby8pKQoKWyFbXShodHRwczovL3d3dy5hcHBsZS5jb20vbmV3c3Jvb20vaW1hZ2VzL3Byb2R1Y3QvaXBob25lL3N0YW5kYXJkL0FwcGxlLWlQaG9uZTEzLVByby1jb2xvci1saW5ldXAtMjIwMzA4X2JpZ19jYXJvdXNlbC5qcGcuc21hbGxfMnguanBnICJBcHBsZSBpUGhvbmUgMTMiKXt3aWR0aD0iNzE0In1dKGh0dHBzOi8vZW5jcnlwdGVkLXRibjAuZ3N0YXRpYy5jb20vaW1hZ2VzP3E9dGJuOkFOZDlHY1JWN1pjN1hwVEVSOGphX1BydHVJeHFzYXBqczAxRWxzdXFLUSZ1c3FwPUNBVSkKCltQaWN0dXJlIFNvdXJjZV0oaHR0cHM6Ly93d3cuYXBwbGUuY29tL25ld3Nyb29tL2ltYWdlcy9wcm9kdWN0L2lwaG9uZS9zdGFuZGFyZC9BcHBsZS1pUGhvbmUxMy1Qcm8tY29sb3ItbGluZXVwLTIyMDMwOF9iaWdfY2Fyb3VzZWwuanBnLnNsaWRlc2hvdy14bGFyZ2UuanBnKQoKIyMgQ29tcGFyaXNvbiBvZiBGZWF0dXJlcwoKKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSsKfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCBTYW1zdW5nIFMyMiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IEFwcGxlIGlQaG9uZSAxMyAgICAgICAgICAgICAgICAgICAgICAgICAgIHwKKz09PT09PT09PT09PT09PT09PT09PT09PT09PT09Kz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0rPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSsKfCAqKlN0YXJ0aW5nIFByaWNlKiogICAgICAgICAgfCBcJDc5OSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IFwkNzk5ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwKKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSsKfCAqKlNjcmVlbiBzaXplKiogICAgICAgICAgICAgfCA2LjEgaW5jaGVzICgyMzQwIHggMTA4MCkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDYuMSBpbmNoZXMgKDI1MzIgeCAxMTcwKSAgICAgICAgICAgICAgICAgIHwKKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSsKfCAqKlJlZnJlc2ggcmF0ZSoqICAgICAgICAgICAgfCA0OEh6LTEyMEh6IGFkYXB0aXZlICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDYwSHogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwKKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSsKfCAqKkNQVSoqICAgICAgICAgICAgICAgICAgICAgfCBTbmFwZHJhZ29uIDggR2VuIDEgKFVTKTsgRXh5bm9zIDIyMDAgKEspICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IEExNSBCaW9uaWMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwKKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSsKfCAqKlJBTSoqICAgICAgICAgICAgICAgICAgICAgfCA4R0IgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDRHQiAoYmFzZWQgb24gdGVhcmRvd25zKSAgICAgICAgICAgICAgICAgIHwKKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSsKfCAqKlN0b3JhZ2UqKiAgICAgICAgICAgICAgICAgfCAxMjhHQiwgMjU2R0IgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEyOEdCLCAyNTZHQiwgNTEyR0IgICAgICAgICAgICAgICAgICAgICAgIHwKKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSsKfCAqKlJlYXIgY2FtZXJhcyoqICAgICAgICAgICAgfCA1ME1QIHdpZGUgKGYvMS44KTsgMTJNUCB1bHRyYXdpZGUgKGYvMi4yKTsgMTBNUCB0ZWxlcGhvdG8gKGYvMi40KSB3aXRoIDN4IG9wdGljYWwgem9vbSB8IDEyTVAgbWFpbiAoZi8xLjYpLCAxMk1QIHVsdHJhd2lkZSAoZi8yLjQpIHwKKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSsKfCAqKkZyb250IGNhbWVyYSoqICAgICAgICAgICAgfCAxME1QIChmLzIuMikgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEyTVAgKGYvMi4yKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwKKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSsKfCAqKkJhdHRlcnkgc2l6ZSoqICAgICAgICAgICAgfCAzLDcwMCBtQWggICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDMsMjI3IG1BaCAoYmFzZWQgb24gdGVhcmRvd25zKSAgICAgICAgICAgIHwKKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSsKfCAqKkJhdHRlcnkgbGlmZSAoSHJzOk1pbnMpKiogfCA3OjUxICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEwOjMzICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwKKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSsKfCAqKkNoYXJnaW5nIHNwZWVkcyoqICAgICAgICAgfCAyNVcgd2lyZWQsIDE1VyB3aXJlbGVzcyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDIwVyB3aXJlZDsgMTVXIHdpcmVsZXNzICAgICAgICAgICAgICAgICAgIHwKKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSsKfCAqKlNpemUqKiAgICAgICAgICAgICAgICAgICAgfCA1LjcgeCAyLjggeCAwLjMgaW5jaGVzICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDUuOCB4IDIuOCB4IDAuMyBpbmNoZXMgICAgICAgICAgICAgICAgICAgIHwKKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSsKfCAqKldlaWdodCoqICAgICAgICAgICAgICAgICAgfCA1Ljkgb3VuY2VzICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDYuMTQgb3VuY2VzICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwKKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSsKfCAqKkNvbG9ycyoqICAgICAgICAgICAgICAgICAgfCBCbGFjaywgd2hpdGUsIGdyZWVuLCBwaW5rIGdvbGQgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IEJsYWNrLCB3aGl0ZSwgYmx1ZSwgcGluaywgcmVkLCBncmVlbiAgICAgIHwKKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSsKClNvdXJjZTogPGh0dHBzOi8vd3d3LnRvbXNndWlkZS5jb20vZmFjZS1vZmYvc2Ftc3VuZy1nYWxheHktczIyLXZzLWlwaG9uZS0xMz4KCiMjIE9iamVjdGl2ZXMgb2Ygb3VyIFJlc2VhcmNoCgotICAgSWRlbnRpZmljYXRpb24gb2YgdGhlIHN0cmVuZ3RocyBhbmQgd2Vha25lc3NlcyBvZiB0aGUgY29tcGV0aXRvcnMgd2hpY2ggY2FuIGhlbHAgdG8gaWRlbnRpZnkgYSBnYXAgaW4gYSBtYXJrZXQgYW5kIGVuaGFuY2luZyB0aGUgb3duIGJ1c2luZXNzIHN0cmF0ZWd5LgoKLSAgIElkZW50aWZpY2F0aW9uIG9mIHN1Z2dlc3Rpb25zIHRvIGN1c3RvbWVycyBhYm91dCB0aGUgcHJvZHVjdHMgYmFzZWQgb24gb3RoZXIgY3VzdG9tZXJzJyBvcGluaW9ucwoKIyMgTWV0aG9kb2xvZ3kgb2Ygb3VyIFJlc2VhcmNoCgojIFR3aXR0ZXIgQW5hbHlzaXMKCmBgYHtyIEluaXRpYWxpc2luZyBQYWNrYWdlcywgaW5jbHVkZT1GQUxTRX0KbGlicmFyeShiYXNlNjRlbmMpCmxpYnJhcnkoZGF0YS50YWJsZSkKbGlicmFyeShkcGx5cikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGdncmFwaCkKbGlicmFyeShodHRwdXYpCmxpYnJhcnkoaHR0cikKbGlicmFyeShpZ3JhcGgpCmxpYnJhcnkob3BlbnNzbCkKbGlicmFyeShwbHlyKQpsaWJyYXJ5KFJDdXJsKQpsaWJyYXJ5KFJPQXV0aCkKbGlicmFyeShydHdlZXQpCmxpYnJhcnkoc2VudGltZW50cikKbGlicmFyeShTbm93YmFsbEMpCmxpYnJhcnkoc3RvcHdvcmRzKQpsaWJyYXJ5KHN0cmluZ3IpCmxpYnJhcnkoc3l1emhldCkKbGlicmFyeSh0ZXh0Y2xlYW4pCmxpYnJhcnkodGV4dG1pbmVSKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KHRpZHl0ZXh0KQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeSh0bSkKbGlicmFyeSh0b3BpY21vZGVscykKbGlicmFyeSh0d2l0dGVSKQpsaWJyYXJ5KHdpZHlyKQpsaWJyYXJ5KHdvcmRjbG91ZCkKYGBgCgpgYGB7ciBTZXR1cCB0d2l0dGVyLCBpbmNsdWRlPUZBTFNFfQojIyMjIHNldHRpbmcgdGhlIHdvcmtpbmcgZGlyZWN0b3J5ICMjIyMKI3NldHdkKCIvVXNlcnMvTGlseS9MaWJyYXJ5L01vYmlsZSBEb2N1bWVudHMvY29tfmFwcGxlfkNsb3VkRG9jcy9UcmluaXR5IENvbGxlZ2UgRHVibGluL0JVNzE0NyBTb2NpYWwgTWVkaWEgQW5hbHlzaXMvR3JvdXAgQXNzaWdubWVudC9Tb2NpYWwtTWVkaWEtQW5hbHl0aWNzIikKCiMjIyMgaW5pdGlhbGl6aW5nIGtleXMgIyMjIwojYmVhcmVyX3Rva2VuPC0iIyMjIyMjIyIKI2NvbnN1bWVyX2tleTwtIiMjIyMjIyMiCiNjb25zdW1lcl9zZWNyZXQ8LSIjIyMjIyMjIgojYWNjZXNzX3Rva2VuPC0iIyMjIyMjIyIKI2FjY2Vzc190b2tlbl9zZWNyZXQ8LSIjIyMjIyMjIgoKI3NldHVwX3R3aXR0ZXJfb2F1dGgoY29uc3VtZXJfa2V5PWNvbnN1bWVyX2tleSwKICAgICAgICAgICAgICAgICAgICAjIGNvbnN1bWVyX3NlY3JldD1jb25zdW1lcl9zZWNyZXQsCiAgICAgICAgICAgICAgICAgICAgIyBhY2Nlc3NfdG9rZW49YWNjZXNzX3Rva2VuLAogICAgICAgICAgICAgICAgICAgICMgYWNjZXNzX3NlY3JldD1hY2Nlc3NfdG9rZW5fc2VjcmV0KQpgYGAKCiMjIERhdGEgRXh0cmFjdGlvbiBhbmQgQ2xlYW5pbmcKCiMjIyBTYW1zdW5nIFMyMgoKV2UgZGVjaWRlZCB0byBleHRyYWN0IGRhdGEgZnJvbSBUd2l0dGVyIHdpdGggdGhlIGtleXdvcmRzICJTYW1zdW5nIFMyMiIgYW5kIHRoZSBoYXNodGFnICJcI3NhbXN1bmdzMjIiIGZyb20gMzEuMDMuMjAyMiAtIDA4LjA0LjIwMjIgYXMgd2UgZG8gbm90IGhhdmUgYSBwcmVtaXVtIGxpY2Vuc2UgdG8gZ2V0IGFjY2VzcyB0byB0aGUgZnVsbCB0aW1lbGluZSBvZiB0d2VldHMgb24gdGhlIFR3aXR0ZXJBUEkuCgpXZSBleGNsdWRlZCBmcm9tIG91ciBxdWVyeSB0aGUgdXNlcnMgU2hvcGVlSUQsIFxfYXJsbGVlIGFuZCBhbGwgcmV0d2VldHMgZm9yIHRoZSBrZXl3b3JkcyAiU2Ftc3VuZyBTMjIiIGJlY2F1c2UgdGhlcmUgd2VyZSBtdWx0aXBsZSB0aG91c2FuZHMgb2YgdHdlZXRzIGFib3V0IGEgY29tcGV0aXRpb24gdG8gd2luIGEgU2Ftc3VuZyBtb2JpbGUgcGhvbmUgd2hpY2ggY2F1c2VkIGEgbG90IG9mIGR1cGxpY2F0ZWQgZGF0YS4KCkFzIHdlbGwsIHdlIGlkZW50aWZpZWQgbmluZSB1c2VycyB3aGljaCB3ZXJlIGNyZWF0aW5nIGFkdmVydGlzaW5nIHNwYW0gYW5kIG5vbi12YWx1YWJsZSB0d2VldHMgdGhhdCB3ZSBoYWQgdG8gZXhjbHVkZTogIndoaXRlc3RvbmVkb21lIiwgIkZyb21Lb3JlYTUiLCAiZG9tZV9nbGFzcyIsICJXaGl0ZXN0b25lX0RFIiwgIndoaXRlc3RvbmVfVUsiLCAianBfd2hpdGVzdG9uZSIsICJXaGl0ZXN0b25lXF9cX0ZSIiwgIldoaXRlc3RvbmVKYXBhbiIsICJXaGl0ZXN0b25lRVUiLgoKSW4gdG90YWwgd2UgY291bGQgZ2F0aGVyIDM4NDYgdHdlZXRzLgoKYGBge3IgRXh0cmFjdGluZyBUd2VldHMgYWJvdXQgU2Ftc3VuZyBmcm9tIFR3aXR0ZXIsIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CiMjIyMgR2V0dGluZyBUd2VldHMgYWJvdXQgU2Ftc3VuZyAjIyMjCiMgc3R3ZWV0czEgPC0gc2VhcmNoVHdpdHRlcigiI3NhbXN1bmdzMjIgLWZpbHRlcjpyZXR3ZWV0cyIsIG49MTAwMDAsIGxhbmc9ImVuIiwgcmV0cnlPblJhdGVMaW1pdCA9IDEwMCkKIyBzZGYxIDwtIHR3TGlzdFRvREYoc3R3ZWV0czEpCiMgVmlldyhzZGYxKQojIAojIHN0d2VldHMyIDwtIHNlYXJjaFR3aXR0ZXIoIlNhbXN1bmcgKyBTMjIgLUBTaG9wZWVJRCAtQF9hcmxsZWUgLWZpbHRlcjpyZXR3ZWV0cyIsIG49MTAwMDAsIGxhbmc9ImVuIiwgcmV0cnlPblJhdGVMaW1pdCA9IDEwMCkKIyBzZGYyIDwtIHR3TGlzdFRvREYoc3R3ZWV0czIpCiMgVmlldyhzZGYyKQojIAojIHNkMl91c2VycyA8LSBzZGYyICU+JQojICAgZGlzdGluY3Qoc2NyZWVuTmFtZSwgaWQpICU+JQojICAgZ3JvdXBfYnkoc2NyZWVuTmFtZSkgJT4lCiMgICBzdW1tYXJpc2UoIm51bWJlciBvZiB0d2VldHMiID0gbigpKQojIFZpZXcoc2QyX3VzZXJzKQojIHN1bShzZDJfdXNlcnMkYG51bWJlciBvZiB0d2VldHNgKQojIAojIGFkX3R3ZWV0cyA8LSBjKCJ3aGl0ZXN0b25lZG9tZSIsICJGcm9tS29yZWE1IiwgImRvbWVfZ2xhc3MiLCAiV2hpdGVzdG9uZV9ERSIsICJ3aGl0ZXN0b25lX1VLIiwgImpwX3doaXRlc3RvbmUiLCAiV2hpdGVzdG9uZV9fRlIiLCAiV2hpdGVzdG9uZUphcGFuIiwgIldoaXRlc3RvbmVFVSIpCiMgCiMgc2RmMl9maWx0ZXIgPC0gc2RmMiAlPiUKIyAgIGZpbHRlcighc2NyZWVuTmFtZSAlaW4lIGFkX3R3ZWV0cykKIyBWaWV3KHNkZjJfZmlsdGVyKQojIAojIHNkMl91c2VyczIgPC0gc2RmMl9maWx0ZXIgJT4lCiMgICBkaXN0aW5jdChzY3JlZW5OYW1lLCBpZCkgJT4lCiMgICBncm91cF9ieShzY3JlZW5OYW1lKSAlPiUKIyAgIHN1bW1hcmlzZSgibnVtYmVyIG9mIHR3ZWV0cyIgPSBuKCkpCiMgVmlldyhzZDJfdXNlcnMyKQojIAojIHNhbXN1bmdfZGYgPC0gcmJpbmQoc2RmMSwgc2RmMl9maWx0ZXIpCiMgVmlldyhzYW1zdW5nX2RmKQojIHdyaXRlLmNzdihzYW1zdW5nX2RmLCJTYW1zdW5nX2RmLmNzdiIpCmBgYAoKT3VyIGluaXRpYWwgZGF0YSBmcmFtZSBoYXMgMTcgYXR0cmlidXRlcy4gWW91IGNhbiBmaW5kIHRoZSBtZWFuaW5nIG9mIGVhY2ggb2YgdGhlIGF0dHJpYnV0ZXMgaGVyZSBvbiB0aGUgW1R3aXR0ZXIgRGV2ZWxvcGVyIFBsYXRmb3JtXShodHRwczovL2RldmVsb3Blci50d2l0dGVyLmNvbS9lbi9kb2NzL3R3aXR0ZXItYXBpL3YxL2RhdGEtZGljdGlvbmFyeS9vYmplY3QtbW9kZWwvdHdlZXQpLgoKYGBge3IgU2Ftc3VuZyBSZWFkIERhdGEsIGVjaG89RkFMU0V9CiMjIyMjIFNhbXN1bmc6IFVzZSB0aGlzIGRhdGFmcmFtZSBmcm9tIG5vdyBvbiBzbyB3ZSB3b3JrIG9uIHNhbWUgZGF0YSAjIyMjIwpzYW1zdW5nX2RmIDwtIHJlYWQuY3N2KCJTYW1zdW5nX2RmLmNzdiIpCmhlYWQoc2Ftc3VuZ19kZikKYGBgCgpJbiB0aGUgZm9sbG93aW5nIGNvZGUgd2UgY2hlY2tlZCB0aGF0IHRoZSBkYXRhLmZyYW1lIHdhcyBjb3JyZWN0bHkgZm9ybWF0dGVkOgoKYGBge3IgU2Ftc3VuZyBEYXRhIFN0cnVjdHVyZSwgZWNobz1GQUxTRX0Kc3RyKHNhbXN1bmdfZGYpCmBgYAoKIyMjIEFwcGxlIGlQaG9uZSAxMwoKV2UgZXh0cmFjdGVkIGRhdGEgZm9yIHRoZSBzZWFyY2ggdGVybXMgImlQaG9uZSAxMyIgZXhjbHVkaW5nIHJldHdlZXRzIGFuZCB0aGUgaGFzaHRhZyAiXCNpcGhvbmUxMyIgZnJvbSB0aGUgVHdpdHRlckFQSS4gU2ltaWxhcmx5LCB0byB0aGUgU2Ftc3VuZyBTMjIgd2UgaGFkIHRvIGV4Y2x1ZGUgY2VydGFpbiB1c2VycyB3aGljaCB3ZXJlIGFkdmVydGlzaW5nICgid2hpdGVzdG9uZWRvbWUiLCAiRnJvbUtvcmVhNSIsICJkb21lZ2xhc3NhcHBsZSIpIGFuZCBjb21wZXRpdGlvbnMgdG8gd2luIGFuIGlQaG9uZSB3aGVuIHJldHdlZXRpbmcgb3IgY29weS1wYXN0aW5nIGEgc3BlY2lmaWMgdGV4dCAoIkpvaW4gdGhlIGV2ZW50IHRvIHdpbiBhbiBpUGhvbmUgMTMhIikuIEFsc28sIHdlIGhhZCBhIGhpZ2ggbnVtYmVyIG9mIHR3ZWV0cyB3aGljaCB3ZXJlIHJhbmRvbWx5IHBvc3RpbmcgYnJhbmQgbmFtZXMsIGUuZy4gInJvbGV4IGlwaG9uZSIgaW4gb25lIHR3ZWV0LgoKSW4gdG90YWwgd2UgY291bGQgZ2F0aGVyIDgzNjkgdHdlZXRzLgoKYGBge3IgRXh0cmFjdGluZyBUd2VldHMgYWJvdXQgQXBwbGUgZnJvbSBUd2l0dGVyLCBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQojIyMjIEdldHRpbmcgVHdlZXRzIGFib3V0IEFwcGxlICMjIyMKIyBhdHdlZXRzMSA8LSBzZWFyY2hUd2l0dGVyKCJpUGhvbmUgKyAxMyAtZmlsdGVyOnJldHdlZXRzIiwgbj0xMDAwMCwgbGFuZz0iZW4iLCByZXRyeU9uUmF0ZUxpbWl0ID0gMTAwKQojIGFkZjEgPC0gdHdMaXN0VG9ERihhdHdlZXRzMSkKIyBWaWV3KGFkZjEpCiMgCiMgYWRmX3VzZXJzIDwtIGFkZjEgJT4lCiMgICBkaXN0aW5jdChzY3JlZW5OYW1lLCBpZCkgJT4lCiMgICBncm91cF9ieShzY3JlZW5OYW1lKSAlPiUKIyAgIHN1bW1hcmlzZSgibnVtYmVyIG9mIHR3ZWV0cyIgPSBuKCkpCiMgVmlldyhhZGZfdXNlcnMpCiMgCiMgYWRmX3JlcGxpZXMgPC0gYWRmMSAlPiUKIyAgIGRpc3RpbmN0KHJlcGx5VG9TTiwgaWQpICU+JQojICAgZ3JvdXBfYnkocmVwbHlUb1NOKSAlPiUKIyAgIHN1bW1hcmlzZSgibnVtYmVyIG9mIHJlcGxpZXMgdG8gdXNlciIgPSBuKCkpCiMgVmlldyhhZGZfcmVwbGllcykKIyAKIyBhcHBsZV9hZF90d2VldHMgPC0gYygid2hpdGVzdG9uZWRvbWUiLCAiRnJvbUtvcmVhNSIsICJkb21lZ2xhc3NhcHBsZSIpCiMgCiMgYWRmX2ZpbHRlciA8LSBhZGYxICU+JQojICAgZmlsdGVyKCFzY3JlZW5OYW1lICVpbiUgYXBwbGVfYWRfdHdlZXRzKQojIFZpZXcoYWRmX2ZpbHRlcikKIyAKIyBhdHdlZXRzMiA8LSBzZWFyY2hUd2l0dGVyKCIjaXBob25lMTMgLWZpbHRlcjpyZXR3ZWV0cyIsIG49MTAwMDAsIGxhbmc9ImVuIiwgcmV0cnlPblJhdGVMaW1pdCA9IDEwMCkKIyBhZGYyIDwtIHR3TGlzdFRvREYoYXR3ZWV0czIpCiMgVmlldyhhZGYyKQojIAojIGFkZl91c2VyczIgPC0gYWRmMiAlPiUKIyAgIGRpc3RpbmN0KHNjcmVlbk5hbWUsIGlkKSAlPiUKIyAgIGdyb3VwX2J5KHNjcmVlbk5hbWUpICU+JQojICAgc3VtbWFyaXNlKCJudW1iZXIgb2YgdHdlZXRzIiA9IG4oKSkKIyBWaWV3KGFkZl91c2VyczIpCiMgCiMgYWRmX3JlcGxpZXMyIDwtIGFkZjIgJT4lCiMgICBkaXN0aW5jdChyZXBseVRvU04sIGlkKSAlPiUKIyAgIGdyb3VwX2J5KHJlcGx5VG9TTikgJT4lCiMgICBzdW1tYXJpc2UoIm51bWJlciBvZiByZXBsaWVzIHRvIHVzZXIiID0gbigpKQojIFZpZXcoYWRmX3JlcGxpZXMpCiMgCiMgYXBwbGVfZGYgPC0gcmJpbmQoYWRmX2ZpbHRlciwgYWRmMikKIyAKIyAjdGhlcmUgaXMgYW5vdGhlciBjb21wZXRpdGlvbiB3aGljaCBkaWQgbm90IG5lZWQgcmV0d2VldHMgb3IgcmVwbHlpbmcgdG8gc29tZW9uZSBzcGVjaWZpY2FsbHkgCiMgI3Blb3BsZSBjb3BpZWQgdGhlIHRleHQgdG8gdGFrZSBwYXJ0LCB0aGVyZWZvcmUsIHRoZSB3b3JkICJ0cmVhc3VyZSIgYW5kICJ3aW4iIHdlcmUgZXhvcmJpdGFudCBpbiBvdXIgYW5hbHlzaXMKIyAjdGhlcmVmb3JlIHdlIGV4Y2x1ZGVkIGFsbCByb3dzIHRoYXQgaGFkIHRoaXMgdGV4dAojIGFwcGxlX2RmIDwtIGFwcGxlX2RmICU+JQojICAgZmlsdGVyKCFncmVwbCgiSm9pbiB0aGUgZXZlbnQgdG8gd2luIGFuIGlQaG9uZSAxMyEiLHRleHQpKSAgJT4lCiMgICBmaWx0ZXIoIWdyZXBsKCJyb2xleCIsdGV4dCkpCiMgCiMgd3JpdGUuY3N2KGFwcGxlX2RmLCJBcHBsZV9kZi5jc3YiKQpgYGAKCk91ciBpbml0aWFsIGRhdGEgZnJhbWUgaGFzIDE3IGF0dHJpYnV0ZXMuIFlvdSBjYW4gZmluZCB0aGUgbWVhbmluZyBvZiBlYWNoIG9mIHRoZSBhdHRyaWJ1dGVzIGhlcmUgb24gdGhlIFtUd2l0dGVyIERldmVsb3BlciBQbGF0Zm9ybV0oaHR0cHM6Ly9kZXZlbG9wZXIudHdpdHRlci5jb20vZW4vZG9jcy90d2l0dGVyLWFwaS92MS9kYXRhLWRpY3Rpb25hcnkvb2JqZWN0LW1vZGVsL3R3ZWV0KS4KCmBgYHtyIEFwcGxlIFJlYWQgRGF0YSwgZWNobz1GQUxTRX0KIyMjIyMgQXBwbGU6IFVzZSB0aGlzIGRhdGFmcmFtZSBmcm9tIG5vdyBvbiBzbyB3ZSB3b3JrIG9uIHNhbWUgZGF0YSAjIyMjIwphcHBsZV9kZiA8LSByZWFkLmNzdigiQXBwbGVfZGYuY3N2IikKaGVhZChhcHBsZV9kZikKCmBgYAoKSW4gdGhlIGZvbGxvd2luZyBjb2RlIHdlIGNoZWNrZWQgdGhhdCB0aGUgZGF0YS5mcmFtZSB3YXMgY29ycmVjdGx5IGZvcm1hdHRlZDoKCmBgYHtyIEFwcGxlIERhdGEgU3RydWN0dXJlLCBlY2hvPUZBTFNFfQpzdHIoYXBwbGVfZGYpCmBgYAoKIyMgSG93IE1hbnkgVXNlcnMgV2VyZSBQb3N0aW5nIEhvdyBNYW55IFR3ZWV0cyBpbiB0aGUgRGF0YXNldD8KCmBgYHtyIFN0YXRpc3RpY3MgU2Ftc3VuZywgaW5jbHVkZT1GQUxTRX0Kc3RhdHNfcyA8LSBzYW1zdW5nX2RmICU+JQogIG11dGF0ZShkYXRlID0gc3Vic3RyKGNyZWF0ZWQsMSwxMCkpCnN0YXRzX3MgPC0gYWdncmVnYXRlKGNiaW5kKGNvdW50X3VzZXJzID0gc2NyZWVuTmFtZSwgY291bnRfdHdlZXRzID0gaWQpIH4gZGF0ZSwgCiAgICAgICAgICBkYXRhID0gc3RhdHNfcywgCiAgICAgICAgICBGVU4gPSBmdW5jdGlvbih4KXtuX2Rpc3RpbmN0KHgpfSkKc3RhdHNfcyA8LSBzdGF0c19zICU+JQogIG11dGF0ZShhdmdfdHdlZXRzX3Blcl91c2VyID0gY291bnRfdHdlZXRzIC8gY291bnRfdXNlcnMpICU+JQogIG11dGF0ZSh3ZWVrZGF5ID0gd2Vla2RheXMoYXMuRGF0ZShkYXRlKSkpCnN0YXRzX3MgPC0gZGF0YS5mcmFtZShzdGF0c19zKQpzdGF0c19zCmBgYAoKYGBge3IgU3RhdGlzdGljcywgaW5jbHVkZT1GQUxTRX0Kc3RhdHNfYSA8LSBhcHBsZV9kZiAlPiUKICBtdXRhdGUoZGF0ZSA9IHN1YnN0cihjcmVhdGVkLDEsMTApKQpzdGF0c19hIDwtIGFnZ3JlZ2F0ZShjYmluZChjb3VudF91c2VycyA9IHNjcmVlbk5hbWUsIGNvdW50X3R3ZWV0cyA9IGlkKSB+IGRhdGUsIAogICAgICAgICAgICAgICAgICAgICBkYXRhID0gc3RhdHNfYSwgCiAgICAgICAgICAgICAgICAgICAgIEZVTiA9IGZ1bmN0aW9uKHgpe25fZGlzdGluY3QoeCl9KQpzdGF0c19hIDwtIHN0YXRzX2EgJT4lCiAgbXV0YXRlKGF2Z190d2VldHNfcGVyX3VzZXIgPSBjb3VudF90d2VldHMgLyBjb3VudF91c2VycykgJT4lCiAgbXV0YXRlKHdlZWtkYXkgPSB3ZWVrZGF5cyhhcy5EYXRlKGRhdGUpKSkKc3RhdHNfYSA8LSBkYXRhLmZyYW1lKHN0YXRzX2EpCnN0YXRzX2EKYGBgCgpXaGlsZSB0aGVyZSB3ZXJlIG9ubHkgMzg0NiB0d2VldHMgZnJvbSB1c2VycyBhYm91dCB0aGUgU2Ftc3VuZyBTMjIsIHRoZXJlIHdlcmUgMi4xNyB0aW1lcyBtb3JlIHR3ZWV0cyBhYm91dCB0aGUgQXBwbGUgaVBob25lIDEzIGR1cmluZyB0aGUgcGVyaW9kIGNvbnNpZGVyZWQuCgpgYGB7ciBTdGF0cywgZWNobz1GQUxTRX0KZ2dwbG90KCkgKyAKICBnZW9tX2xpbmUoZGF0YT1zdGF0c19zLCBhZXMoeD1kYXRlLCB5ID0gY291bnRfdHdlZXRzLCBjb2xvciA9ICJTYW1zdW5nIFMyMiIsIGdyb3VwID0gMSkpICsgCiAgZ2VvbV9saW5lKGRhdGE9c3RhdHNfYSwgYWVzKHg9ZGF0ZSwgeSA9IGNvdW50X3R3ZWV0cywgY29sb3IgPSAiQXBwbGUgaVBob25lIDEzIiwgZ3JvdXAgPSAxKSkgKwogIGdlb21fcG9pbnQoZGF0YT1zdGF0c19zLCBhZXMoeD1kYXRlLCB5PWNvdW50X3VzZXJzLCBjb2xvciA9IlNhbXN1bmcgUzIyIiwgZ3JvdXA9MSkpKwogIGdlb21fcG9pbnQoZGF0YT1zdGF0c19hLCBhZXMoeD1kYXRlLCB5PWNvdW50X3VzZXJzLCBjb2xvciA9IkFwcGxlIGlQaG9uZSAxMyIsIGdyb3VwPTEpKSArCiAgeWxhYigiTnVtYmVyIG9mIFR3ZWV0cyBvciBVc2VycyIpICsKICB4bGFiKCJkYXRlIikgKwogIGdndGl0bGUoIlRoZSBOdW1iZXIgb2YgVXNlcnMgKHBvaW50cykgYW5kIFR3ZWV0cyAobGluZSkgb3ZlciBUaW1lIikKYGBgCgpPbiAzIG91dCBvZiA5IGRheXMgU2Ftc3VuZyBTMjIgaGFkIG1vcmUgdHdlZXRzIHRoYW4gaVBob25lIDEzLiBPbiB0aGUgb3RoZXIgZGF5cyBBcHBsZSBleGNlZWRlZCB0aGUgbnVtYmVyIG9mIHR3ZWV0cyBleHRyZW1lbHkuIFN1cnByaXNpbmdseSwgdGhlIG51bWJlciBvZiB0d2VldHMgYW5kIHVzZXJzIHBlciBkYXkgZm9yIHRoZSBTYW1zdW5nIFMyMiByZW1haW5zIGNvbnN0YW50IHdoaWxlIHRoZXJlIGFyZSBvbmx5IGEgZmV3IHR3ZWV0cyBhYm91dCB0aGUgaVBob25lIDEzIGluIHRoZSBmaXJzdCAzIGRheXMgYW5kIGEgaGlnaCB2b2x1bWUgb2YgdHdlZXRzIGZyb20gM25kIEFwcmlsIHVudGlsIDd0aCBBcHJpbCAyMDIyLiBUaGVyZSB3YXMgbm90IG9ubHkgbW9yZSB0d2VldHMgYnV0IGFsc28gYSBsYXJnZXIgZ3JvdXAgb2YgdXNlcnMgcG9zdGluZyBhYm91dCBpUGhvbmUgMTMuIFdlIGNvdWxkIG5vdCBpZGVudGlmeSBhIHNwZWNpZmljIHJlYXNvbiBmb3IgdGhpcyBwaGVub21lbm9uIGJlY2F1c2UgdGhlIGxhc3Qgb2ZmaWNpYWwgQXBwbGUgZXZlbnQgd2FzIGluIE1hcmNoIDIwMjIgYW5kIG5vdCBpbiB0aGUgdGltZSBwZXJpb2Qgd2UgdGVzdGVkLgoKVGhlcmUgaXMgbm8gc2ltaWxhciBpbmRpY2F0b3IgZnJvbSBbR29vZ2xlIFRyZW5kc10oaHR0cHM6Ly90cmVuZHMuZ29vZ2xlLmNvbS90cmVuZHMvZXhwbG9yZT9kYXRlPTIwMjItMDMtMzElMjAyMDIyLTA0LTA4JnE9aVBob25lJTIwMTMsU2Ftc3VuZyUyMFMyMixBcHBsZSxTYW1zdW5nKSBvciBvdGhlciBzb3VyY2VzLiBUaGUgc2VhcmNoIHRlcm1zIGlQaG9uZSAxMywgU2Ftc3VuZyBTMjIsIEFwcGxlIGFuZCBTYW1zdW5nIGFyZSByZWxhdGl2ZWx5IGNvbnN0YW50IG92ZXIgdGltZSBhcyB5b3UgY2FuIHNlZSBmcm9tIHRoZSBpbWFnZSBiZWxvdyAoU2NyZWVuc2hvdCBmcm9tIEdvb2dsZSBUcmVuZHMpLiBJdCBjYW4gYmUgbm90ZWQgdGhhdCBBcHBsZSBpcyBtb3JlIGxpa2VseSB0byBiZSBsb29rZWQgdXAgdGhhbiBTYW1zdW5nIGFzIHdlbGwgYXMgdGhlIGlQaG9uZSAxMyBpcyBtb3JlIHBvcHVsYXIgb24gR29vZ2xlIFNlYXJjaCB0aGFuIFNhbXN1bmcgUzIyLiBUaGlzIGdpdmVzIHVzIGEgZmlyc3QgaW1wcmVzc2lvbiB0aGF0IHRoZSBpUGhvbmUgMTMgbW9kZWwgcmVjZWl2ZXMgaW4gZ2VuZXJhbCBtb3JlIGF0dGVudGlvbi4KCiFbXShpbWFnZXMvcGFzdGUtMkQ1MDA0QzIucG5nKQoKVGhlcmUgYXJlIG1vcmUgdHdlZXRzIHRoYW4gdXNlcnMgd2hpY2ggaW5kaWNhdGVzIHRoYXQgc29tZSB1c2VycyB1c3VhbGx5IHBvc3QgbW9yZSB0aGFuIG9uZSB0d2VldC4gV2UgY2FsY3VsYXRlZCBhIHJhdGlvIGZvciB0aGlzOiBgYXZnX3R3ZWV0c19wZXJfdXNlciA9IHR3ZWV0cyBwZXIgZGF5IC8gdXNlcnMgcGVyIGRheWAuCgpgYGB7ciBVc2VyIFR3ZWV0aW5nIEJlaGF2aW91ciwgZWNobz1GQUxTRX0KY29tcF90d19wX3UgPC0gZGF0YS5mcmFtZShkYXRlPXBhc3RlKGRhdGU9c3Vic3RyKHN0YXRzX2EkZGF0ZSw2LDEwKSwgd2Vla2RheT1zdGF0c19hJHdlZWtkYXkpLCBzdGF0c19hJGF2Z190d2VldHNfcGVyX3VzZXIsIHN0YXRzX3MkYXZnX3R3ZWV0c19wZXJfdXNlcikKZ2dwbG90KCkrCiAgZ2VvbV9saW5lKGRhdGE9Y29tcF90d19wX3UsIGFlcyh4PWRhdGUsIHk9c3RhdHNfYS5hdmdfdHdlZXRzX3Blcl91c2VyLCBncm91cD0xLCBjb2xvcj0iQXBwbGUiKSkrIAogIGdlb21fbGluZShkYXRhPWNvbXBfdHdfcF91LCBhZXMoeD1kYXRlLCB5PXN0YXRzX3MuYXZnX3R3ZWV0c19wZXJfdXNlciwgZ3JvdXA9MSwgY29sb3I9IlNhbXN1bmciKSkrCiAgdGhlbWUoYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA1KSkrCiAgeWxhYigiQXZlcmFnZSB0d2VldCBwZXIgdXNlciIpCmBgYAoKSXQgaXMgaW50ZXJlc3RpbmcgdGhvdWdoIHRoZXJlIHdlcmUgbGVzcyBjb252ZXJzYXRpb24gYWJvdXQgQXBwbGUgaW4gdGhlIGZpcnN0IHRocmVlIGRheXMsIHRoZXJlIHdlcmUgc3RhdGlzdGljYWxseSBtb3JlIHBlb3BsZSBpbnZvbHZlZCwgc28gaXQgc2VlbXMgdG8gYmUgYSBjb252ZXJzYXRpb24gYmV0d2VlbiBhIHNtYWxsZXIgZ3JvdXAgb2YgdXNlcnMuIFdlIHNlZSB0aGUgc2FtZSBmb3IgU2Ftc3VuZyBTMjIgYmV0d2VlbiA0dGggQXByaWwgdG8gNnRoIEFwcmlsIDIwMjIuCgojIyBXb3JkY2xvdWQKCiMjIyBEYXRhIFByZXByb2Nlc3NpbmcKCldlIGRlY2lkZWQgdG8gcHJlcHJvY2VzcyB0aGUgZGF0YSBiYXNlZCBvbiB0aGUgZm9sbG93aW5nIHN0ZXBzOgoKLSAgIEFsbCB0ZXh0IHdhcyBjb252ZXJ0ZWQgdG8gbG93ZXIgY2FzZSwgZS5nLiBIZWxsbyB0byBoZWxsby4KCi0gICBBbGwgY29udHJhY3Rpb25zIHdlcmUgY29udmVydGVkIHRvIHRoZSBsb25nZXIgZm9ybSwgZS5nLiBkb24ndCB0byBkbyBub3QKCi0gICBBbGwgY29tbW9uIGludGVybmV0IHNsYW5nIHdhcyBjb252ZXJ0ZWQgdG8gZm9ybWFsIEVuZ2xpc2gsIGUuZy4gVEdJRiB0byBUaGFua3MgR29kIGl0IGlzIEZyaWRheQoKLSAgIEhhc2h0YWdzIChcIykgd2VyZSByZW1vdmVkCgotICAgV29yZCBlbG9uZ2F0aW9uIHdhcyByZXBsYWNlZCB0byB0aGUgdXN1YWwgd29yZCBmb3JtLCBlLmcuIGhlZWVlZXkgdG8gaGV5CgotICAgQWxsIG5vbi1BU0NJSSBjaGFyYWN0ZXJzIHdlcmUgcmVwbGFjZWQgd2l0aCBlcXVpdmFsZW50IG9yIHJlbW92ZWQsICoqwqkqKiB0byAoQykKCi0gICBXaGl0ZSBzcGFjZSB3aXRoaW4gdGhlIHN0cmluZyBpcyByZWR1Y2VkIHRvIG9uZSB3aGl0ZSBzcGFjZQoKLSAgIFdoaXRlIHNwYWNlIGF0IHRoZSBzdGFydCBhbmQgZW5kIG9mIHRoZSBzdHJpbmcgd2FzIHJlbW92ZWQKCi0gICAiUlQiLCBpbXBsaWNhdGluZyB0aGF0IGl0cyBhIHJldHdlZXQgd2FzIHJlbW92ZWQKCi0gICBhbGwgbGlua3Mgd2VyZSByZW1vdmVkIGJhc2VkIG9uIHRoZSBzdGFydCBvZiAiaHR0cCIKCi0gICBhbGwgQHVzZXJuYW1lIHdlcmUgcmVtb3ZlZAoKLSAgIHB1bmN0dWF0aW9uIHdlcmUgcmVtb3ZlZAoKLSAgIHN0b3Agd29yZHMgd2VyZSByZW1vdmVkIGJhc2VkIG9uIHRoZSBSZWdFeCBhcHByb2FjaAoKYGBge3IgV29yZGNsb3VkIEJhc2ljcywgaW5jbHVkZT1GQUxTRX0KIyMjIyMgYnVpbGRpbmcgd29yZGNsb3VkICMjIyMjCnBhbDwtIGJyZXdlci5wYWwoOCwiRGFyazIiKQpzdG9wd29yZHNfcmVnZXggPC0gcGFzdGUoc3RvcHdvcmRzKCdlbicpLCBjb2xsYXBzZSA9ICdcXGJ8XFxiJykKc3RvcHdvcmRzX3JlZ2V4IDwtIHBhc3RlMCgnXFxiJywgc3RvcHdvcmRzX3JlZ2V4LCAnXFxiJykKYGBgCgpgYGB7ciBTYW1zdW5nIFByZXByb2Nlc3NpbmcsIGluY2x1ZGU9RkFMU0V9CndvcmRfcyA8LSBzYW1zdW5nX2RmJHRleHQgJT4lCiAgc3RyX3RvX2xvd2VyKCkgJT4lICNhbGwgdGV4dCB0byBsb3dlciBjYXNlCiAgcmVwbGFjZV9jb250cmFjdGlvbigpICU+JSAjcmVwbGFjZXMgY29udHJhY3Rpb25zIHRvIGxvbmdlciBmb3JtCiAgcmVwbGFjZV9pbnRlcm5ldF9zbGFuZygpICU+JSAjcmVwbGFjZXMgY29tbW9uIGludGVybmV0IHNsYW5nCiAgcmVwbGFjZV9oYXNoKHJlcGxhY2VtZW50ID0gIiIpICU+JSAjcmVtb3ZlcyBoYXNodGFncwogIHJlcGxhY2Vfd29yZF9lbG9uZ2F0aW9uKCkgJT4lICNyZW1vdmVzIHdvcmQgZWxvbmdhdGlvbiwgZS5nLiAiaGVlZWVleSIgdG8gImhleSIKICAjcmVwbGFjZV9lbW9qaSgpICU+JSAjcmVwbGFjZXMgZW1vamlzIHdpdGggdGhlIHdvcmQgZm9ybSAjd2UgZWxpbWluYXRlIHRoaXMgZnJvbSB3b3JkIHByZXByb2Nlc3NpbmcgYmVjYXVzZSB3ZSBkb24ndCB3YW50IGVtb2ppIHdvcmRzIHRvIGJlIHdpdGhpbiB0aGUgd29yZCBjbG91ZAogICNyZXBsYWNlX2Vtb2ppX2lkZW50aWZpZXIoKSAlPiUgI3JlcGxhY2VzIGVtb2ppIGlkZW50aWZpZXJzIHRvIHdvcmQgZm9ybSAjd2UgZWxpbWluYXRlIHRoaXMgZnJvbSB3b3JkIHByZXByb2Nlc3NpbmcgYmVjYXVzZSB3ZSBkb24ndCB3YW50IGVtb2ppIHdvcmRzIHRvIGJlIHdpdGhpbiB0aGUgd29yZCBjbG91ZAogICNyZXBsYWNlX25vbl9hc2NpaSgpICU+JSAjcmVwbGFjZXMgY29tbW9uIG5vbi1BU0NJSSBjaGFyYWN0ZXJzLiAjd2UgZWxpbWluYXRlIHRoaXMgZnJvbSB3b3JkIHByZXByb2Nlc3NpbmcgYmVjYXVzZSB3ZSBkb24ndCB3YW50IGVtb2ppIHdvcmRzIHRvIGJlIHdpdGhpbiB0aGUgd29yZCBjbG91ZAogIHN0cl9zcXVpc2goKSAlPiUgI3JlZHVjZXMgcmVwZWF0ZWQgd2hpdGVzcGFjZSBpbnNpZGUgYSBzdHJpbmcKICBzdHJfdHJpbSgpICU+JSAjcmVtb3ZlcyB3aGl0ZXNwYWNlIGZyb20gc3RhcnQgYW5kIGVuZCBvZiBzdHJpbmcKICB7Z3N1YigiKFJUfHZpYSkoKD86XFxiXFxXKkBcXHcrKSspIiwiIiwuKX0gJT4lICNyZW1vdmUgUlQgKHJldHdlZXRzKQogIHtnc3ViKCJodHRwW15bOmJsYW5rOl1dKyIsIiIsLil9ICU+JSAjcmVtb3ZlIGxpbmtzIHRoYXQgc3RhcnQgd2l0aCBodHRwCiAge2dzdWIoIkBcXHUrIiwiIiwuKX0gJT4lICNyZW1vdmUgbmFtZXMgCiAge2dzdWIoJ0BcXHcrJywgJycsIC4pfSAlPiUgIyByZW1vdmUgYXQgcGVvcGxlCiAge2dzdWIoIltbOnB1bmN0Ol1dIiwiICIsLil9ICU+JSNyZW1vdmUgcHVuY3R1YXRpb24KICB7Z3N1YigiW15bOmFsbnVtOl1dIiwiICIsLil9JT4lI3JlbW92ZSBwdW5jdHVhdGlvbgogIHJlbW92ZU51bWJlcnMoKSAlPiUKICByZW1vdmVXb3JkcyhzdG9wd29yZHMoImVuZ2xpc2giKSkgJT4lCiAgc3RyaW5ncjo6c3RyX3JlcGxhY2VfYWxsKHN0b3B3b3Jkc19yZWdleCwgJycpICU+JSAjcmVtb3ZlIHN0b3Agd29yZHMKICB1bmlxdWUoKSAjcmVtb3ZlIGR1cGxpY2F0ZXMKYGBgCgpgYGB7ciBBcHBsZSBQcmVwcm9jZXNzaW5nLCBpbmNsdWRlPUZBTFNFfQp3b3JkX2EgPC0gYXBwbGVfZGYkdGV4dCAlPiUKICBzdHJfdG9fbG93ZXIoKSAlPiUgI2FsbCB0ZXh0IHRvIGxvd2VyIGNhc2UKICByZXBsYWNlX2NvbnRyYWN0aW9uKCkgJT4lICNyZXBsYWNlcyBjb250cmFjdGlvbnMgdG8gbG9uZ2VyIGZvcm0KICByZXBsYWNlX2ludGVybmV0X3NsYW5nKCkgJT4lICNyZXBsYWNlcyBjb21tb24gaW50ZXJuZXQgc2xhbmcKICByZXBsYWNlX2hhc2gocmVwbGFjZW1lbnQgPSAiIikgJT4lICNyZW1vdmVzIGhhc2h0YWdzCiAgcmVwbGFjZV93b3JkX2Vsb25nYXRpb24oKSAlPiUgI3JlbW92ZXMgd29yZCBlbG9uZ2F0aW9uLCBlLmcuICJoZWVlZWV5IiB0byAiaGV5IgogICNyZXBsYWNlX2Vtb2ppKCkgJT4lICNyZXBsYWNlcyBlbW9qaXMgd2l0aCB0aGUgd29yZCBmb3JtICN3ZSBlbGltaW5hdGUgdGhpcyBmcm9tIHdvcmQgcHJlcHJvY2Vzc2luZyBiZWNhdXNlIHdlIGRvbid0IHdhbnQgZW1vamkgd29yZHMgdG8gYmUgd2l0aGluIHRoZSB3b3JkIGNsb3VkCiAgI3JlcGxhY2VfZW1vamlfaWRlbnRpZmllcigpICU+JSAjcmVwbGFjZXMgZW1vamkgaWRlbnRpZmllcnMgdG8gd29yZCBmb3JtICN3ZSBlbGltaW5hdGUgdGhpcyBmcm9tIHdvcmQgcHJlcHJvY2Vzc2luZyBiZWNhdXNlIHdlIGRvbid0IHdhbnQgZW1vamkgd29yZHMgdG8gYmUgd2l0aGluIHRoZSB3b3JkIGNsb3VkCiAgI3JlcGxhY2Vfbm9uX2FzY2lpKCkgJT4lICNyZXBsYWNlcyBjb21tb24gbm9uLUFTQ0lJIGNoYXJhY3RlcnMuICN3ZSBlbGltaW5hdGUgdGhpcyBmcm9tIHdvcmQgcHJlcHJvY2Vzc2luZyBiZWNhdXNlIHdlIGRvbid0IHdhbnQgZW1vamkgd29yZHMgdG8gYmUgd2l0aGluIHRoZSB3b3JkIGNsb3VkCiAgc3RyX3NxdWlzaCgpICU+JSAjcmVkdWNlcyByZXBlYXRlZCB3aGl0ZXNwYWNlIGluc2lkZSBhIHN0cmluZwogIHN0cl90cmltKCkgJT4lICNyZW1vdmVzIHdoaXRlc3BhY2UgZnJvbSBzdGFydCBhbmQgZW5kIG9mIHN0cmluZwogIHtnc3ViKCIoUlR8dmlhKSgoPzpcXGJcXFcqQFxcdyspKykiLCIiLC4pfSAlPiUgI3JlbW92ZSBSVCAocmV0d2VldHMpCiAge2dzdWIoImh0dHBbXls6Ymxhbms6XV0rIiwiIiwuKX0gJT4lICNyZW1vdmUgbGlua3MgdGhhdCBzdGFydCB3aXRoIGh0dHAKICB7Z3N1YigiQFxcdSsiLCIiLC4pfSAlPiUgI3JlbW92ZSBuYW1lcyAKICB7Z3N1YignQFxcdysnLCAnJywgLil9ICU+JSAjIHJlbW92ZSBhdCBwZW9wbGUKICB7Z3N1YigiW1s6cHVuY3Q6XV0iLCIgIiwuKX0gJT4lI3JlbW92ZSBwdW5jdHVhdGlvbgogIHtnc3ViKCJbXls6YWxudW06XV0iLCIgIiwuKX0lPiUjcmVtb3ZlIHB1bmN0dWF0aW9uCiAgcmVtb3ZlTnVtYmVycygpICU+JQogIHJlbW92ZVdvcmRzKHN0b3B3b3JkcygiZW5nbGlzaCIpKSAlPiUKICBzdHJpbmdyOjpzdHJfcmVwbGFjZV9hbGwoc3RvcHdvcmRzX3JlZ2V4LCAnJyklPiUgI3JlbW92ZSBzdG9wIHdvcmRzCiAgdW5pcXVlKCkgI3JlbW92ZSBkdXBsaWNhdGVzCmBgYAoKIyMjIFJlc3VsdHMKCmBgYHtyIFdvcmRjbG91ZCBTYW1zdW5nLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQp3b3JkY2xvdWQod29yZF9zLCBtaW4uZnJlcSA9IDYwLCBtYXgud29yZHMgPSA0MCwgcmFuZG9tLm9yZGVyID0gRkFMU0UsIGNvbG9yPSBwYWwpCmBgYAoKU2Ftc3VuZyBTMjIgdXNlcnMgbWVudGlvbmVkIFNhbXN1bmcsIEdhbGF4eSAod2hpY2ggaXMgdGhlIHNlcmllcyBvZiB0aGUgUzIyKSBhbmQgVWx0cmEgKHdoaWNoIGlzIGEgc3BlY2lmaWMgbW9kZWwpLiBUaGUgVWx0cmEgbW9kZWwgaXMgY29tcGFyYWJsZSB0byB0aGUgaVBob25lIDEzIFByby4KCkFsc28gaVBob25lLCBQcm8sIE1heCwgTm90ZSAmIE9uZVBsdXMgYXJlIG1lbnRpb25lZCB3aGljaCBhcmUgb3RoZXIgY29tcGFyYWJsZSBzbWFydHBob25lcyBpbiB0aGUgbWFya2V0LgoKT3RoZXIgd29yZHMgdGhhdCBhcmUgb2Z0ZW4gbWVudGlvbmVkIGJlbG9uZyB0byBzcGVjaWZpY2F0aW9ucyB0aGF0IHVzZXJzIHRhbGtlZCBhYm91dDoKCi0gICBhbmRyb2lkLCB1cGRhdGUsIHNlY3VyaXR5CgotICAgY2FtZXJhLCBwaXhlbCwgdmlkZW8KCi0gICBmZWF0dXJlcwoKLSAgIG1lZGlhdGVrCgotICAgc2NyZWVuCgotICAgYW1wCgotICAgY2FzZQoKYGBge3IgV29yZGNsb3VkIEFwcGxlLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQp3b3JkY2xvdWQod29yZF9hLCBtaW4uZnJlcSA9IDYwLCBtYXgud29yZHMgPSA0MCwgcmFuZG9tLm9yZGVyID0gRkFMU0UsIGNvbG9yPSBwYWwpCmBgYAoKV2UgY2FuIGlkZW50aWZ5IHRoYXQgQXBwbGUgaVBob25lIGlzIG1lbnRpb25lZCBpbiB0aGUgdmFyaWFudHMgUHJvLCBNaW5pIGFuZCBNYXguIFBybyBzZWVtcyB0byBiZSB0aGUgbW9zdCBpbXBvcnRhbnQgb25lLCB0aGVuIE1heCBhbmQgdGhlbiB0aGUgTWluaS4KCkFzIHdpdGggdGhlIFNhbXN1bmcgUzIyLCBhbHNvIGhlcmUgaXQgaXMgbWVudGlvbmVkIHdpdGggIlVsdHJhIiwgIkdhbGF4eSIgYW5kICJTYW1zdW5nIi4KClRoZSBzcGVjaWZpY2F0aW9ucyBvZiB0aGUgcGhvbmUgdGhhdCB1c2VycyB0YWxrZWQgYWJvdXQgd2VyZToKCi0gICBwaXhlbCwgY2FtZXJhCgotICAgYmF0dGVyeSwgYW1wCgotICAgcHJpY2UKCi0gICBjYXNlCgotICAgZ3JlZW4KCkZvciBpUGhvbmUgMTMsIHdlIGNhbiBub3RpY2UgdGhhdCBzb21lIGFkamVjdGl2ZXMgYW5kIHZlcmJzIHdlcmUgbWVudGlvbmVkIGEgbG90OgoKYXZhaWxhYmxlLCBidXksIHdpbiwgZnJlZSwgc3RpbGwsIG5vdywgZ29vZCwgYmV0dGVyLCBiZXN0LCBsaWtlLCB3aWxsLCBnZXQsIHdhbnQsIG5lZWQsIGNhbgoKV2Ugd2lsbCBpZGVudGlmeSB0b3BpY3MgZnVydGhlciBkdXJpbmcgb3VyIGFuYWx5c2lzIHVzaW5nIExEQSBUb3BpYyBNb2RlbGxpbmcuCgojIyMgSW5zaWdodHMKCkJvdGggbW9kZWxzIGFyZSBtZW50aW9uZWQgd2l0aCB0aGVpciBjYW1lcmEgYW5kIHBpeGVsIGJ1dCBvbmx5IFNhbXN1bmcgaGFzIHRoZSB3b3JkICJ2aWRlbyIgbWVudGlvbmVkIGEgbG90LiBXZSBpZGVudGlmaWVkIGluIG91ciBwcmUtcmVzZWFyY2ggYWJvdXQgdGhlIHBob25lcyB0aGF0IGJvdGggY29tcGFuaWVzIGFkdmVydGlzZSB0aGVpciBzbWFydHBob25lcyBiYXNlZCBvbiB0aGUgY2FtZXJhLiBOb25lIG9mIGJvdGggbWVudGlvbnMgYWJvdXQgcG9zaXRpdmUgYWJpbGl0aWVzIGluIHRoZSB2aWRlbyByZWNvcmRpbmcgaW4gdGhlaXIgbWFpbiBhZHZlcnRpc2VtZW50LgoKRm9yIFNhbXN1bmcgUzIyIHVzZXJzIGl0IHNlZW1zIHRvIGJlIGltcG9ydGFudCB0aGF0IGEgbmV3IHVwZGF0ZSBoYXMgYmVlbiByZWxlYXNlZC4gQSBuZXcgQW5kcm9pZCBPUyB1cGRhdGUgZm9yIHRoZSBzZXJpZXMgUzIyIGhhcyBiZWVuIHJlbGVhc2VkIGluIEFwcmlsIDIwMjIgYW5kIHVwZGF0ZWQgc2VjdXJpdHkgbWVhc3VyZW1lbnRzIGFuZCBicm91Z2h0IG5ldyBmZWF0dXJlcy4KCkZvciBBcHBsZSBpUGhvbmUgMTMgaXQgaGFzIGJlZW4gdGFsa2VkIGEgbG90IGFib3V0IGdyZWVuLiBUaGUgZ2VuZXJhdGlvbiAxMyBoYXMgYmVlbiB0aGUgZmlyc3QgRmxhZ3NoaXAgbW9kZWwgdG8gYmUgcHJvZHVjZWQgaW4gdGhpcyBjb2xvdXIsIHRoZXJlZm9yZSBpdCBtYWtlcyBzZW5zZSB0aGF0IHBlb3BsZSBkaXNjdXNzIGFib3V0IGl0LgoKIyMgU2VudGltZW50IEFuYWx5c2lzCgojIyMgUHJlcHJvY2Vzc2luZyBUd2VldHMKCldlIG5lZWQgdG8gcHJlcHJvY2VzcyBkYXRhIHRoaXMgdGltZSBhZGRpdGlvbmFsbHkgd2l0aCB0aGUgZm9sbG93aW5nIHN0ZXBzOgoKLSAgIEVtb2ppcyB3ZXJlIHJlcGxhY2VkIGJ5IHRoZSB3b3JkIGZvcm0sIGUuZy4gU21pbGluZyBlbW9qaSB0byBzbWlsaW5nCgotICAgRW1vamkgSWRlbnRpZmllciB3ZXJlIHJlcGxhY2VkIGJ5IHRoZSB3b3JkIGZvcm0sIGUuZy4gOi0pIHRvIHNtaWxpbmcKCmBgYHtyIFNhbXN1bmcgUzIyIGRhdGEsIGVjaG89VFJVRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0Kc3RvcHdvcmRzX3JlZ2V4IDwtIHBhc3RlKHN0b3B3b3JkcygnZW4nKSwgY29sbGFwc2UgPSAnXFxifFxcYicpCnN0b3B3b3Jkc19yZWdleCA8LSBwYXN0ZTAoJ1xcYicsIHN0b3B3b3Jkc19yZWdleCwgJ1xcYicpCgpTYW1zdW5nX2RmIDwtIHNhbXN1bmdfZGYkdGV4dCAlPiUKICBzdHJfdG9fbG93ZXIoKSAlPiUgI2FsbCB0ZXh0IHRvIGxvd2VyIGNhc2UKICByZXBsYWNlX2NvbnRyYWN0aW9uKCkgJT4lICNyZXBsYWNlcyBjb250cmFjdGlvbnMgdG8gbG9uZ2VyIGZvcm0KICByZXBsYWNlX2ludGVybmV0X3NsYW5nKCkgJT4lICNyZXBsYWNlcyBjb21tb24gaW50ZXJuZXQgc2xhbmcKICByZXBsYWNlX2hhc2gocmVwbGFjZW1lbnQgPSAiIikgJT4lICNyZW1vdmVzIGhhc2h0YWdzCiAgcmVwbGFjZV93b3JkX2Vsb25nYXRpb24oKSAlPiUgI3JlbW92ZXMgd29yZCBlbG9uZ2F0aW9uLCBlLmcuICJoZWVlZWV5IiB0byAiaGV5IgogIHJlcGxhY2VfZW1vamkoKSAlPiUgI3JlcGxhY2VzIGVtb2ppcyB3aXRoIHRoZSB3b3JkIGZvcm0gCiAgcmVwbGFjZV9lbW9qaV9pZGVudGlmaWVyKCkgJT4lICNyZXBsYWNlcyBlbW9qaSBpZGVudGlmaWVycyB0byB3b3JkIGZvcm0gCiAgcmVwbGFjZV9ub25fYXNjaWkoKSAlPiUgI3JlcGxhY2VzIGNvbW1vbiBub24tQVNDSUkgY2hhcmFjdGVycy4gCiAgc3RyX3NxdWlzaCgpICU+JSAjcmVkdWNlcyByZXBlYXRlZCB3aGl0ZXNwYWNlIGluc2lkZSBhIHN0cmluZwogIHN0cl90cmltKCkgJT4lICNyZW1vdmVzIHdoaXRlc3BhY2UgZnJvbSBzdGFydCBhbmQgZW5kIG9mIHN0cmluZwogIHtnc3ViKCIoUlR8dmlhKSgoPzpcXGJcXFcqQFxcdyspKykiLCIiLC4pfSAlPiUgI3JlbW92ZSBSVCAocmV0d2VldHMpCiAge2dzdWIoImh0dHBbXls6Ymxhbms6XV0rIiwiIiwuKX0gJT4lICNyZW1vdmUgbGlua3MgdGhhdCBzdGFydCB3aXRoIGh0dHAKICB7Z3N1YigiQFxcdSsiLCIiLC4pfSAlPiUgI3JlbW92ZSBuYW1lcyAKICB7Z3N1YignQFxcdysnLCAnJywgLil9ICU+JSAjIHJlbW92ZSBhdCBwZW9wbGUKICB7Z3N1YigiW1s6cHVuY3Q6XV0iLCIgIiwuKX0gJT4lI3JlbW92ZSBwdW5jdHVhdGlvbgogIHtnc3ViKCJbXls6YWxudW06XV0iLCIgIiwuKX0lPiUjcmVtb3ZlIHB1bmN0dWF0aW9uCiAge2dzdWIoInBybyIsIiAiLC4pfSU+JSNyZW1vdmVzIHRoZSB3b3JkICJwcm8iIGJlY2F1c2UgaXRzIGEgZGlmZmVyZW50IGNvbnRleHQgaGVyZWluCiAgc3RyaW5ncjo6c3RyX3JlcGxhY2VfYWxsKHN0b3B3b3Jkc19yZWdleCwgJycpICU+JSAjcmVtb3ZlIHN0b3Agd29yZHMKICB1bmlxdWUoKSNyZW1vdmUgZHVwbGljYXRlcwoKdGFpbChTYW1zdW5nX2RmKQpgYGAKCmBgYHtyIEFwcGxlIGlQaG9uZSAxMyBkYXRhLCBlY2hvPVRSVUUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CkFwcGxlX2RmIDwtIGFwcGxlX2RmJHRleHQgJT4lCiAgc3RyX3RvX2xvd2VyKCkgJT4lICNhbGwgdGV4dCB0byBsb3dlciBjYXNlCiAgcmVwbGFjZV9jb250cmFjdGlvbigpICU+JSAjcmVwbGFjZXMgY29udHJhY3Rpb25zIHRvIGxvbmdlciBmb3JtCiAgcmVwbGFjZV9pbnRlcm5ldF9zbGFuZygpICU+JSAjcmVwbGFjZXMgY29tbW9uIGludGVybmV0IHNsYW5nCiAgcmVwbGFjZV9oYXNoKHJlcGxhY2VtZW50ID0gIiIpICU+JSAjcmVtb3ZlcyBoYXNodGFncwogIHJlcGxhY2Vfd29yZF9lbG9uZ2F0aW9uKCkgJT4lICNyZW1vdmVzIHdvcmQgZWxvbmdhdGlvbiwgZS5nLiAiaGVlZWVleSIgdG8gImhleSIKICByZXBsYWNlX2Vtb2ppKCkgJT4lICNyZXBsYWNlcyBlbW9qaXMgd2l0aCB0aGUgd29yZCBmb3JtIAogIHJlcGxhY2VfZW1vamlfaWRlbnRpZmllcigpICU+JSAjcmVwbGFjZXMgZW1vamkgaWRlbnRpZmllcnMgdG8gd29yZCBmb3JtIAogIHJlcGxhY2Vfbm9uX2FzY2lpKCkgJT4lICNyZXBsYWNlcyBjb21tb24gbm9uLUFTQ0lJIGNoYXJhY3RlcnMuIAogIHN0cl9zcXVpc2goKSAlPiUgI3JlZHVjZXMgcmVwZWF0ZWQgd2hpdGVzcGFjZSBpbnNpZGUgYSBzdHJpbmcKICBzdHJfdHJpbSgpICU+JSAjcmVtb3ZlcyB3aGl0ZXNwYWNlIGZyb20gc3RhcnQgYW5kIGVuZCBvZiBzdHJpbmcKICB7Z3N1YigiKFJUfHZpYSkoKD86XFxiXFxXKkBcXHcrKSspIiwiIiwuKX0gJT4lICNyZW1vdmUgUlQgKHJldHdlZXRzKQogIHtnc3ViKCJodHRwW15bOmJsYW5rOl1dKyIsIiIsLil9ICU+JSAjcmVtb3ZlIGxpbmtzIHRoYXQgc3RhcnQgd2l0aCBodHRwCiAge2dzdWIoIkBcXHUrIiwiIiwuKX0gJT4lICNyZW1vdmUgbmFtZXMgCiAge2dzdWIoJ0BcXHcrJywgJycsIC4pfSAlPiUgIyByZW1vdmUgYXQgcGVvcGxlCiAge2dzdWIoIltbOnB1bmN0Ol1dIiwiICIsLil9ICU+JSNyZW1vdmUgcHVuY3R1YXRpb24KICB7Z3N1YigiW15bOmFsbnVtOl1dIiwiICIsLil9JT4lI3JlbW92ZSBwdW5jdHVhdGlvbgogIHtnc3ViKCJwcm8iLCIgIiwuKX0lPiUjcmVtb3ZlcyB0aGUgd29yZCAicHJvIiBiZWNhdXNlIGl0cyBhIGRpZmZlcmVudCBjb250ZXh0IGhlcmVpbgogIHN0cmluZ3I6OnN0cl9yZXBsYWNlX2FsbChzdG9wd29yZHNfcmVnZXgsICcnKSAlPiUgI3JlbW92ZSBzdG9wIHdvcmRzCiAgdW5pcXVlKCkgI3JlbW92ZSBkdXBsaWNhdGVzCiAgCiAgCnRhaWwoQXBwbGVfZGYpCmBgYAoKIyMjIFNlbnRpbWVudHMgaW4gVHdlZXRzCgpUaGUgc2VudGltZW50IGFuYWx5c2lzCgpgYGB7ciBTYW1zdW5nIFNlbnRpbWVudCBTY29yZXMsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiMjIyMjIHNlbnRpbWVudCBhbmFseXNpcyAjIyMjIwpteXNlbnRpbWVudDwtIGdldF9ucmNfc2VudGltZW50KFNhbXN1bmdfZGYpCnNlbnRpbWVudHNjb3JlczwtIGRhdGEuZnJhbWUoY29sU3VtcyhteXNlbnRpbWVudFssXSkpCgojIyMjIyMgZ2V0dGluZyBzZW50aW1lbnQgc2NvcmVzICMjIyMjIwpuYW1lcyhzZW50aW1lbnRzY29yZXMpPC0ic2NvcmUiCnNlbnRpbWVudHNjb3JlczwtY2JpbmQoInNlbnRpbWVudCI9cm93bmFtZXMoc2VudGltZW50c2NvcmVzKSxzZW50aW1lbnRzY29yZXMpCnJvd25hbWVzKHNlbnRpbWVudHNjb3Jlcyk8LU5VTEwKCiMjIyMjIyBwbG90dGluZyBzZW50aW1lbnQgc2NvcmVzICMjIyMjIwpnZ3Bsb3QoZGF0YT1zZW50aW1lbnRzY29yZXMsYWVzKHg9c2VudGltZW50LHk9c2NvcmUpKSsKICBnZW9tX2JhcihhZXMoZmlsbD1zZW50aW1lbnQpLHN0YXQ9ImlkZW50aXR5IikrIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikrCiAgeGxhYigic2VudGltZW50IikgK3lsYWIoInNjb3JlIikrIGdndGl0bGUoIlRvdGFsIFNlbnRpbWVudCBTY29yZSBiYXNlZCBvbiBUd2VldHMgYWJvdXQgU2Ftc3VuZyIpCmBgYAoKYGBge3IgQXBwbGUgU2VudGltZW50IFNjb3JlLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojIyMjIyBzZW50aW1lbnQgYW5hbHlzaXMgIyMjIyMKbXlzZW50aW1lbnRfYXBwbGU8LSBnZXRfbnJjX3NlbnRpbWVudChBcHBsZV9kZikgCnNlbnRpbWVudHNjb3Jlc19hcHBsZTwtIGRhdGEuZnJhbWUoY29sU3VtcyhteXNlbnRpbWVudF9hcHBsZVssXSkpCgojIyMjIyMgZ2V0dGluZyBzZW50aW1lbnQgc2NvcmVzICMjIyMjIwpuYW1lcyhzZW50aW1lbnRzY29yZXNfYXBwbGUpPC0ic2NvcmUiCnNlbnRpbWVudHNjb3Jlc19hcHBsZTwtY2JpbmQoInNlbnRpbWVudCI9cm93bmFtZXMoc2VudGltZW50c2NvcmVzX2FwcGxlKSxzZW50aW1lbnRzY29yZXNfYXBwbGUpCnJvd25hbWVzKHNlbnRpbWVudHNjb3Jlc19hcHBsZSk8LU5VTEwKCiMjIyMjIyBwbG90dGluZyBzZW50aW1lbnQgc2NvcmVzICMjIyMjIwpnZ3Bsb3QoZGF0YT1zZW50aW1lbnRzY29yZXNfYXBwbGUsYWVzKHg9c2VudGltZW50LHk9c2NvcmUpKSsKICBnZW9tX2JhcihhZXMoZmlsbD1zZW50aW1lbnQpLHN0YXQ9ImlkZW50aXR5IikrIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikrCiAgeGxhYigic2VudGltZW50IikgK3lsYWIoInNjb3JlIikrIGdndGl0bGUoIlRvdGFsIFNlbnRpbWVudCBTY29yZSBiYXNlZCBvbiBUd2VldHMgYWJvdXQgQXBwbGUiKQpgYGAKCmBgYHtyIENvbXBhcmlzb24sIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnJlbGF0aXZlX2NvbXBfc2VudGltZW50IDwtIGRhdGEuZnJhbWUoU2VudGltZW50ID0gc2VudGltZW50c2NvcmVzX2FwcGxlJHNlbnRpbWVudCwgQXBwbGVfaVBob25lXzEzID0gc2VudGltZW50c2NvcmVzX2FwcGxlJHNjb3JlL3N1bShzZW50aW1lbnRzY29yZXNfYXBwbGUkc2NvcmUpKjEwMCwgU2Ftc3VuZ19TMjIgPSBzZW50aW1lbnRzY29yZXMkc2NvcmUvc3VtKHNlbnRpbWVudHNjb3JlcyRzY29yZSkqMTAwKSAlPiUKICBtZWx0KGlkLnZhcnMgPSAxLCB2YXJpYWJsZS5uYW1lID0gInZhcmlhYmxlIiwKICAgICAgICAgICB2YWx1ZS5uYW1lPSJzY29yZSIpCgpnZ3Bsb3QocmVsYXRpdmVfY29tcF9zZW50aW1lbnQsIGFlcyh4PSBTZW50aW1lbnQsIHk9IHNjb3JlLCBmaWxsPXZhcmlhYmxlKSkgKwogIGdlb21fYmFyKHBvc2l0aW9uPSJkb2RnZSIsICBzdGF0PSJpZGVudGl0eSIpICsKICB4bGFiKCJzZW50aW1lbnQiKSAreWxhYigicGVyY2VudGFnZSIpKyBnZ3RpdGxlKCJSZWxhdGl2ZSBTZW50aW1lbnQgU2NvcmUgYmFzZWQgb24gVHdlZXRzIGFib3V0IEFwcGxlIGFuZCBTYW1zdW5nIikKYGBgCgpPbiB0aGUgZmlyc3QgbG9vaywgc2VudGltZW50cyBhcmUgc2ltaWxhciBmb3IgYm90aCBzbWFydHBob25lIG1vZGVscyBhbmQgYXJlIGNvbW1lbnRlZCBvbiB3aXRoIGhpZ2hseSBwb3NpdGl2ZSBzZW50aW1lbnRzLiBUaGlzIG1lYW5zIHRoYXQgb24gYm90aCBtb2RlbHMsIHVzZXJzIGFyZSBnZW5lcmFsbHkgc3BlYWtpbmcgcG9zaXRpdmVseSBhYm91dCB0aGVpciBzbWFydHBob25lLgoKU2Ftc3VuZyBTMjIgaGFzIG1vcmUgdHJ1c3QgYW5kIGFudGljaXBhdGlvbiB3aGlsZSBpUGhvbmUgMTMgYnJpbmdzIG1vcmUgam95IHRvIGl0cyB1c2VycyBidXQgYWxzbyBtb3JlIHNhZG5lc3MsIHN1cnByaXNlLCBmZWFyIGFuZCBkaXNndXN0LgoKYGBge3IgQXBwbGUgU2VudGltZW50IFN0YXRpc3RpY3MsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiMjIyMjIyBTZW50aW1lbnRyIHNjb3JlICMjIyMjIyMKc2VudGltZW50cl9hcHBsZSA8LSBzZW50aW1lbnRfYnkoQXBwbGVfZGYsIGJ5PU5VTEwpCiMgWW91IGNhbiBzZWUgdGhlIHNlbnRpbWVudCBwZXIgdHdlZXQgSUQ6CmdncGxvdChkYXRhPXNlbnRpbWVudHJfYXBwbGUsYWVzKHg9ZWxlbWVudF9pZCx5PWF2ZV9zZW50aW1lbnQsIGNvbG9yPWF2ZV9zZW50aW1lbnQpKSsKICBnZW9tX2xpbmUoKQojIFlvdSBjYW4gc2VlIHRoZSBzdW1tYXJ5IG9mIG1pbmltdW0sIElRUiwgbWVkaWFuIGFuZCBtZWFuIGZvciBhbGwgdmFyaWFibGVzLiBGb3IgdXMsIHdvcmRfY291bnQgYW5kIGF2ZV9zZW50aW1lbnQgYXJlIG1vc3RseSBpbnRlcmVzdGluZzoKc3VtbWFyeShzZW50aW1lbnRyX2FwcGxlKQoKIyBZb3UgY2FuIHNlZSB0aGUgdmFyaWFuY2UgYW5kIHN0YW5kYXJkIGRldmlhdGlvbiBmb3IgdGhlIFNlbnRpbWVudCBTY29yZSAmIFdvcmQgQ291bnQ6CmRhdGEuZnJhbWUoIiAiPSBjKCJBdmVyYWdlIiwgIlZhcmlhbmNlIiwgIlN0YW5kYXJkIERldmlhdGlvbiIpLAoiU2VudGltZW50IFNjb3JlIiA9IGMocm91bmQobWVhbihzZW50aW1lbnRyX2FwcGxlJGF2ZV9zZW50aW1lbnQpLDIpLCByb3VuZCh2YXIoc2VudGltZW50cl9hcHBsZSRhdmVfc2VudGltZW50KSwyKSwKcm91bmQoc2Qoc2VudGltZW50cl9hcHBsZSRhdmVfc2VudGltZW50KSwyKSksIAoiV29yZCBDb3VudCI9Yyhyb3VuZChtZWFuKHNlbnRpbWVudHJfYXBwbGUkd29yZF9jb3VudCksMiksIHJvdW5kKHZhcihzZW50aW1lbnRyX2FwcGxlJHdvcmRfY291bnQpLDIpLApyb3VuZChzZChzZW50aW1lbnRyX2FwcGxlJHdvcmRfY291bnQpLDIpKSkKYGBgCgpgYGB7ciBTYW1zdW5nIFNlbnRpbWVudCBTdGF0aXN0aWNzLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojIyMjIyBTZW50aW1lbnRyIHNjb3JlICMjIyMjIwpzZW50aW1lbnRyX3NhbXN1bmcgPC0gc2VudGltZW50X2J5KFNhbXN1bmdfZGYsIGJ5PU5VTEwpCiMgWW91IGNhbiBzZWUgdGhlIHNlbnRpbWVudCBwZXIgdHdlZXQgSUQ6CmdncGxvdChkYXRhPXNlbnRpbWVudHJfc2Ftc3VuZyxhZXMoeD1lbGVtZW50X2lkLHk9YXZlX3NlbnRpbWVudCwgY29sb3I9YXZlX3NlbnRpbWVudCkpKwogIGdlb21fbGluZSgpCgojIFlvdSBjYW4gc2VlIHRoZSBzdW1tYXJ5IG9mIG1pbmltdW0sIElRUiwgbWVkaWFuIGFuZCBtZWFuIGZvciBhbGwgdmFyaWFibGVzLiBGb3IgdXMsIHdvcmRfY291bnQgYW5kIGF2ZV9zZW50aW1lbnQgYXJlIG1vc3RseSBpbnRlcmVzdGluZzoKc3VtbWFyeShzZW50aW1lbnRyX3NhbXN1bmcpCgojIFlvdSBjYW4gc2VlIHRoZSB2YXJpYW5jZSBhbmQgc3RhbmRhcmQgZGV2aWF0aW9uIGZvciB0aGUgU2VudGltZW50IFNjb3JlICYgV29yZCBDb3VudDoKZGF0YS5mcmFtZSgiICI9IGMoIkF2ZXJhZ2UiLCAiVmFyaWFuY2UiLCAiU3RhbmRhcmQgRGV2aWF0aW9uIiksCiJTZW50aW1lbnQgU2NvcmUiID0gYyhyb3VuZChtZWFuKHNlbnRpbWVudHJfc2Ftc3VuZyRhdmVfc2VudGltZW50KSwyKSwgcm91bmQodmFyKHNlbnRpbWVudHJfc2Ftc3VuZyRhdmVfc2VudGltZW50KSwyKSwKcm91bmQoc2Qoc2VudGltZW50cl9zYW1zdW5nJGF2ZV9zZW50aW1lbnQpLDIpKSwgCiJXb3JkIENvdW50Ij1jKHJvdW5kKG1lYW4oc2VudGltZW50cl9zYW1zdW5nJHdvcmRfY291bnQpLDIpLCByb3VuZCh2YXIoc2VudGltZW50cl9zYW1zdW5nJHdvcmRfY291bnQpLDIpLApyb3VuZChzZChzZW50aW1lbnRyX3NhbXN1bmckd29yZF9jb3VudCksMikpKQpgYGAKClNhbXN1bmcgUzIyIHR3ZWV0cyB3ZXJlIG9uIGF2ZXJhZ2UgMTAuNCB3b3JkcyBsb25nIHdoaWxlIEFwcGxlIGlQaG9uZSAxMyB0d2VldHMgaGFkIDkuOSB3b3Jkcy4gVGhlIHR3ZWV0IHdpdGggdGhlIG1heGltdW0gbnVtYmVyIG9mIHdvcmRzIHdhcyBhYm91dCBpUGhvbmUgMTMgd2l0aCAxMzUgaWRlbnRpZmllZCB3b3Jkcy4gU2Ftc3VuZyBTMjIgd2l0aCAzNCB3b3JkcyBtYXhpbXVtIHdvcmRzIGlzIHF1aXRlIHNob3J0ZXIuCgpUaGUgc2VudGltZW50ciBwYWNrYWdlIGluIFIgZXN0aW1hdGVzIHRoZSBzZW50aW1lbnQgcG9sYXJpdHkgYnkgc2VudGVuY2UuIFRoZSBhdmVyYWdlIHNlbnRpbWVudCBmb3IgaVBob25lIDEzIHdhcyBoaWdoZXIgZGlzdHJpYnV0ZWQgd2l0aCBhIHJhbmdlIGZyb20gLTEuNiB0byArMS45IHdpdGggaXRzIGF2ZXJhZ2UgYXQgMC4yNiB3aGlsZSBTYW1zdW5nIGhhZCBhIHNlbnRpbWVudCBwb2xhcml0eSBmcm9tIC0xLjEgdG8gKzEuNiB3aXRoIGl0cyBhdmVyYWdlIGF0IDAuMTUuIFRoZSBoaWdoZXIgdmFyaWFuY2Ugd2l0aGluIHRoZSBkYXRhIGlzIGlkZW50aWNhbCB0byBvdXIgZmluZGluZ3MgZnJvbSB0aGUgcGxvdCAiUmVsYXRpdmUgU2VudGltZW50IFNjb3JlIGJhc2VkIG9uIFR3ZWV0cyBhYm91dCBBcHBsZSBhbmQgU2Ftc3VuZyIgZWFybGllci4gV2UgY2FuIHNlZSBmcm9tIHRoaXMgdGhhdCBpUGhvbmUgMTMgdXNlcnMgYXJlIGluIGdlbmVyYWwgbW9yZSBlbW90aW9uYWwgLSBpbiBhIG5lZ2F0aXZlIGFuZCBwb3NpdGl2ZSBkaXJlY3Rpb24gLSB0aGFuIFNhbXN1bmcgUzIyIHVzZXJzLiBXZSBhc3N1bWUgdGhhdCBwZW9wbGUgYXJlIGVtb3Rpb25hbGx5IG1vcmUgZGVwZW5kZW50IG9uIHRoZWlyIGlQaG9uZSAxMyB0aGFuIFNhbXN1bmcgUzIyLgoKVG8gc2VlIHRoZSBzZW50aW1lbnRzIHBlciB0d2VldCwgZ2VuZXJhdGUgdGhpcyBIVE1MIGZpbGVzOgoKYGBge3IgSFRNTCBSZXBvcnRzLCBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQojIEhUTUwgd2l0aCBhbGwgdHdlZXRzIGhpZ2hsaWdodGVkIGJ5IGl0cyBzZW50aW1lbnQgcG9sYXJpdHkgc2NvcmU6CiMgCiMgIyBBcHBsZSBpUGhvbmUgMTMKIyBzZW50aW1lbnRyX2h0bWxfYSA8LSBzZW50aW1lbnRyX2FwcGxlICU+JQojICAgc2VudGltZW50X2J5KGJ5PU5VTEwpJT4lCiMgICBoaWdobGlnaHQoKQojIAojICMgU2Ftc3VuZyBTMjIKIyBzZW50aW1lbnRyX2h0bWxfcyA8LSBzZW50aW1lbnRyX3NhbXN1bmcgJT4lCiMgICBzZW50aW1lbnRfYnkoYnk9TlVMTCklPiUKIyAgIGhpZ2hsaWdodCgpCgpgYGAKCiMjIyBTZW50aW1lbnQgVGVybXMKCk5vdyB3ZSB3YW50IHRvIGV4dHJhY3QgdGhlIHNlbnRpbWVudCB0ZXJtcyBmb3IgYm90aCBwaG9uZXMuIFdoYXQgaXMgbGlrZWQgYnkgdGhlIHVzZXJzPyBXaGF0IGlzIG5vdD8KCiMjIyMgU2Ftc3VuZyBTMjIKCmBgYHtyIFNhbXN1bmcgLSBQb3NpdGl2ZSBTZW50aW1lbnRzLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpzZW50aW1lbnR0ZXJtc19zIDwtIGF0dHJpYnV0ZXMoZXh0cmFjdF9zZW50aW1lbnRfdGVybXMoU2Ftc3VuZ19kZikpJGNvdW50ICU+JQogIG11dGF0ZSh3ZWlnaHRfaW5fcGVyYyA9IHJvdW5kKHBvbGFyaXR5Km4vc3VtKHBvbGFyaXR5Km4pKjEwMCxkaWdpdHM9MikpICU+JQogIGFycmFuZ2UoZGVzYyh3ZWlnaHRfaW5fcGVyYykpICU+JQogIGZpbHRlcihhYnMocG9sYXJpdHkpPjAuMDEpCgpoZWFkKHNlbnRpbWVudHRlcm1zX3MsMTApCmBgYAoKYGBge3IgU2Ftc3VuZyBQb3NpdGl2ZSBXb3JkcywgZWNobz1GQUxTRX0KI25ncmFtID0gMQpiZ19kZl9zIDwtIGRhdGEuZnJhbWUod29yZF9zKQoKc19iaWdyYW0gPC0gYmdfZGZfcyAlPiUKICB1bm5lc3RfdG9rZW5zKG91dHB1dD1iaWdyYW1zLCBpbnB1dD13b3JkX3MsIHRva2VuPSJ3b3JkcyIsIGZvcm1hdD0gInRleHQiKQoKc19iaWdyYW1fY291bnRlZCA8LSBzX2JpZ3JhbSAlPiUgY291bnQoKQpzX2JpZ3JhbV9jb3VudGVkJHNlbnRpbWVudCA8LSBnZXRfc2VudGltZW50KHNfYmlncmFtX2NvdW50ZWQkYmlncmFtcykKCmdncGxvdChzX2JpZ3JhbV9jb3VudGVkLCBhZXMoeD1iaWdyYW1zLCB5PWZyZXEpKSsKICBnZW9tX2NvbCgpCnNfYmlncmFtX3dpdGhfc2VudGltZW50IDwtIHNfYmlncmFtX2NvdW50ZWQgJT4lCiAgbXV0YXRlKHdlaWdodGFnZSA9IHNlbnRpbWVudCpmcmVxKSAlPiUKICBhcnJhbmdlKGRlc2Mod2VpZ2h0YWdlKSkgJT4lCiAgdG9wX24oMjUpCgpnZ3Bsb3Qoc19iaWdyYW1fd2l0aF9zZW50aW1lbnQsIGFlcyh4PWJpZ3JhbXMsIHk9d2VpZ2h0YWdlKSkrCiAgZ2VvbV9jb2woKSsKICB0aGVtZShheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDUpKSsKICB4bGFiKCJQb3NpdGl2ZSBXb3JkIikgKwogIGdndGl0bGUoIlJlbGF0aXZlIEltcG9ydGFuY2Ugb2YgUG9zaXRpdmUgV29yZHMiKQpgYGAKCmBgYHtyIFNhbXN1bmcgLSBOZWdhdGl2ZSBTZW50aW1lbnRzLCBlY2hvPUZBTFNFfQp0YWlsKHNlbnRpbWVudHRlcm1zX3MsMTApCmBgYAoKYGBge3IgU2Ftc3VuZywgZWNobz1GQUxTRX0KIyMjIyMgQ3JlYXRpbmcgYSBwbG90IG9mIHRoZSBuZWdhdGl2ZSB3b3JkcyBtb3N0IGZyZXF1ZW50bHkgdXNlZCAjIyMjIwoKc19iaWdyYW1fd2l0aF9uZWdfc2VudGltZW50IDwtIHNfYmlncmFtX2NvdW50ZWQgJT4lCiAgbXV0YXRlKHdlaWdodGFnZSA9IHNlbnRpbWVudCpmcmVxKSAlPiUKICBhcnJhbmdlKGRlc2Mod2VpZ2h0YWdlKSkgJT4lCiAgdGFpbCgyNSkKCmdncGxvdChzX2JpZ3JhbV93aXRoX25lZ19zZW50aW1lbnQsIGFlcyh4PWJpZ3JhbXMsIHk9LXdlaWdodGFnZSkpKwogIHRoZW1lKGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gNSkpKwogIGdlb21fY29sKCkrCiAgICB4bGFiKCJOZWdhdGl2ZSBXb3JkIikgKwogIGdndGl0bGUoIlJlbGF0aXZlIEltcG9ydGFuY2Ugb2YgTmVnYXRpdmUgV29yZHMiKQoKYGBgCgpTY2FuZGFsIGlzIHJlbGF0ZWQgdG8gdGhlIEdPUyBhcHAgdGhhdCBzbG93ZWQgU2Ftc3VuZyBwaG9uZXMgZG93biBvbiBwdXJwb3NlIHRvIHNhdmUgYmF0dGVyeSBsaWZlIHdpdGhvdXQgbm90aWZ5aW5nIHRoZSB1c2VyIGFib3V0IGl0LgoKIyMjIyBBcHBsZSBpUGhvbmUgMTMKCmBgYHtyIEFwcGxlIC0gUG9zaXRpdmUgU2VudGltZW50LCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpzZW50aW1lbnR0ZXJtc19hIDwtIGF0dHJpYnV0ZXMoZXh0cmFjdF9zZW50aW1lbnRfdGVybXMoQXBwbGVfZGYpKSRjb3VudCAlPiUKICBtdXRhdGUod2VpZ2h0X2luX3BlcmMgPSByb3VuZChwb2xhcml0eSpuL3N1bShwb2xhcml0eSpuKSoxMDAsZGlnaXRzPTIpKSAlPiUKICBhcnJhbmdlKGRlc2Mod2VpZ2h0X2luX3BlcmMpKSAlPiUKICBmaWx0ZXIoYWJzKHBvbGFyaXR5KT4wLjAxKQoKaGVhZChzZW50aW1lbnR0ZXJtc19hLCAxMCkKYGBgCgpgYGB7ciBBcHBsZSBQb3NpdGl2ZSBXb3JkcywgZWNobz1GQUxTRX0KIyMjIyMgQ3JlYXRpbmcgYSBwbG90IG9mIHRoZSBwb3NpdGl2ZSB3b3JkcyBtb3N0IGZyZXF1ZW50bHkgdXNlZCAjIyMjIwoKYmdfZGZfYSA8LSBkYXRhLmZyYW1lKHdvcmRfYSkKCmFfYmlncmFtIDwtIGJnX2RmX2EgJT4lCiAgdW5uZXN0X3Rva2VucyhvdXRwdXQ9YmlncmFtcywgaW5wdXQ9d29yZF9hLCB0b2tlbj0id29yZHMiLCBmb3JtYXQ9ICJ0ZXh0IikKCmFfYmlncmFtX2NvdW50ZWQgPC0gYV9iaWdyYW0gJT4lIGNvdW50KCkKYV9iaWdyYW1fY291bnRlZCRzZW50aW1lbnQgPC0gZ2V0X3NlbnRpbWVudChhX2JpZ3JhbV9jb3VudGVkJGJpZ3JhbXMpCgojIGdncGxvdChhX2JpZ3JhbV9jb3VudGVkLCBhZXMoeD1iaWdyYW1zLCB5PWZyZXEpKSsKIyAgIGdlb21fY29sKCkKYV9iaWdyYW1fd2l0aF9zZW50aW1lbnQgPC0gYV9iaWdyYW1fY291bnRlZCAlPiUKICBtdXRhdGUod2VpZ2h0YWdlID0gc2VudGltZW50KmZyZXEpICU+JQogIGFycmFuZ2UoZGVzYyh3ZWlnaHRhZ2UpKSAlPiUKICB0b3BfbigyNSkKCmdncGxvdChhX2JpZ3JhbV93aXRoX3NlbnRpbWVudCwgYWVzKHg9YmlncmFtcywgeT13ZWlnaHRhZ2UpKSsKICB0aGVtZShheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDUpKSsKICBnZW9tX2NvbCgpICArCiAgeGxhYigiUG9zaXRpdmUgV29yZCIpICsKICBnZ3RpdGxlKCJSZWxhdGl2ZSBJbXBvcnRhbmNlIG9mIFBvc2l0aXZlIFdvcmRzIikKYGBgCgpgYGB7ciBBcHBsZSAtIE5lZ2F0aXZlIFNlbnRpbWVudCwgZWNobz1GQUxTRX0KdGFpbChzZW50aW1lbnR0ZXJtc19hLDEwKQpgYGAKCmBgYHtyIEFwcGxlLCBlY2hvPUZBTFNFfQojIyMjIyBDcmVhdGluZyBhIHBsb3Qgb2YgdGhlIG5lZ2F0aXZlIHdvcmRzIG1vc3QgZnJlcXVlbnRseSB1c2VkICMjIyMjCgphX2JpZ3JhbV93aXRoX25lZ19zZW50aW1lbnQgPC0gYV9iaWdyYW1fY291bnRlZCAlPiUKICBtdXRhdGUod2VpZ2h0YWdlID0gc2VudGltZW50KmZyZXEpICU+JQogIGFycmFuZ2UoZGVzYyh3ZWlnaHRhZ2UpKSAlPiUKICB0YWlsKDI1KQoKZ2dwbG90KGFfYmlncmFtX3dpdGhfbmVnX3NlbnRpbWVudCwgYWVzKHg9YmlncmFtcywgeT0td2VpZ2h0YWdlKSkrCiAgICB0aGVtZShheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDUpKSsKICAgIGdlb21fY29sKCkrCiAgICB4bGFiKCJOZWdhdGl2ZSBXb3JkIikgKwogICAgZ2d0aXRsZSgiUmVsYXRpdmUgSW1wb3J0YW5jZSBvZiBOZWdhdGl2ZSBXb3JkcyIpCmBgYAoKIyMgV29yZCBDb3JyZWxhdGlvbgoKIyMjIFNhbXN1bmcgUzIyCgpgYGB7ciBDb3JyZWxhdGlvblNhbXN1bmcxLCBlY2hvPUZBTFNFfQpzX3dvcmRzX3Blcl90d2VldCA8LSBkYXRhLmZyYW1lKGJnX2RmX3MpICU+JQogIGRwbHlyOjptdXRhdGUodHdlZXQgPSByb3dfbnVtYmVyKCkpICU+JQogIHVubmVzdF90b2tlbnMob3V0cHV0PWJpZ3JhbXMsIGlucHV0PXdvcmRfcywgZm9ybWF0PSAidGV4dCIsIHRva2VuID0gIm5ncmFtcyIsIG49MSkKCnNfd29yZF9wYWlycyA8LSBzX3dvcmRzX3Blcl90d2VldCAlPiUKICBwYWlyd2lzZV9jb3VudChiaWdyYW1zLCB0d2VldCwgc29ydCA9IFRSVUUpCgpzX3dvcmRfY29ycyA8LSBzX3dvcmRzX3Blcl90d2VldCAlPiUKICBncm91cF9ieShiaWdyYW1zKSAlPiUKICBmaWx0ZXIobigpID49IDIwKSAlPiUKICBwYWlyd2lzZV9jb3IoYmlncmFtcywgdHdlZXQsIHNvcnQgPSBUUlVFKQoKc193b3JkX2NvcnMKCnNfd29yZF9jb3JzICU+JQogIGZpbHRlcihpdGVtMSAlaW4lIGMoImFuZHJvaWQiLCAidXBkYXRlIiwgInNlY3VyaXR5IiwiY2FtZXJhIiwgInBpeGVsIiwgInZpZGVvIiwiZmVhdHVyZXMiLCAibWVkaWF0ZWsiLCJzY3JlZW4iLCJhbXAiLCJjYXNlIikpICU+JQogIGdyb3VwX2J5KGl0ZW0xKSAlPiUKICBzbGljZV9tYXgoY29ycmVsYXRpb24sIG4gPSA2KSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgbXV0YXRlKGl0ZW0yID0gcmVvcmRlcihpdGVtMiwgY29ycmVsYXRpb24pKSAlPiUKICBnZ3Bsb3QoYWVzKGl0ZW0yLCBjb3JyZWxhdGlvbikpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogIGZhY2V0X3dyYXAofiBpdGVtMSwgc2NhbGVzID0gImZyZWUiKSArCiAgY29vcmRfZmxpcCgpCgpzX3dvcmRfY29ycyAlPiUKICBmaWx0ZXIoaXRlbTEgJWluJSBjKCJhdmFpbGFibGUiLCAiYnV5Iiwid2luIiwgImZyZWUiLCJzdGlsbCIsIm5vdyIsICJnb29kIiwgImJldHRlciIsICJiZXN0IiwgImxpa2UiLCJ3aWxsIiwgImdldCIsICJ3YW50IiwgIm5lZWQiLCAiY2FuIikpICU+JQogIGdyb3VwX2J5KGl0ZW0xKSAlPiUKICBzbGljZV9tYXgoY29ycmVsYXRpb24sIG4gPSA2KSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgbXV0YXRlKGl0ZW0yID0gcmVvcmRlcihpdGVtMiwgY29ycmVsYXRpb24pKSAlPiUKICBnZ3Bsb3QoYWVzKGl0ZW0yLCBjb3JyZWxhdGlvbikpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogIGZhY2V0X3dyYXAofiBpdGVtMSwgc2NhbGVzID0gImZyZWUiKSArCiAgY29vcmRfZmxpcCgpCmBgYAoKYGBge3IgQ29ycmVsYXRpb25TYW1zdW5nLCBlY2hvPUZBTFNFfQpzX3dvcmRfY29ycyAlPiUKICBmaWx0ZXIoY29ycmVsYXRpb24gPiAuMjgpICU+JQogIGdyYXBoX2Zyb21fZGF0YV9mcmFtZSgpICU+JQogIGdncmFwaChsYXlvdXQgPSAiZnIiKSArCiAgZ2VvbV9lZGdlX2xpbmsoYWVzKGVkZ2VfYWxwaGEgPSBjb3JyZWxhdGlvbiksIHNob3cubGVnZW5kID0gRkFMU0UpICsKICBnZW9tX25vZGVfcG9pbnQoY29sb3IgPSAibGlnaHRibHVlIiwgc2l6ZSA9IDUpICsKICBnZW9tX25vZGVfdGV4dChhZXMobGFiZWwgPSBuYW1lKSwgcmVwZWwgPSBUUlVFKSArCiAgdGhlbWVfdm9pZCgpCmBgYAoKIyMjIEFwcGxlIGlQaG9uZSAxMwoKYGBge3IgQ29ycmVsYXRpb25BcHBsZTEsIGVjaG89RkFMU0V9CmFfd29yZHNfcGVyX3R3ZWV0IDwtIGRhdGEuZnJhbWUoYmdfZGZfYSkgJT4lCiAgZHBseXI6Om11dGF0ZSh0d2VldCA9IHJvd19udW1iZXIoKSkgJT4lCiAgdW5uZXN0X3Rva2VucyhvdXRwdXQ9YmlncmFtcywgaW5wdXQ9d29yZF9hLCBmb3JtYXQ9ICJ0ZXh0IiwgdG9rZW4gPSAibmdyYW1zIiwgbj0xKQoKYV93b3JkX3BhaXJzIDwtIGFfd29yZHNfcGVyX3R3ZWV0ICU+JQogIHBhaXJ3aXNlX2NvdW50KGJpZ3JhbXMsIHR3ZWV0LCBzb3J0ID0gVFJVRSkKCmFfd29yZF9jb3JzIDwtIGFfd29yZHNfcGVyX3R3ZWV0ICU+JQogIGdyb3VwX2J5KGJpZ3JhbXMpICU+JQogIGZpbHRlcihuKCkgPj0gMjApICU+JQogIHBhaXJ3aXNlX2NvcihiaWdyYW1zLCB0d2VldCwgc29ydCA9IFRSVUUpCgphX3dvcmRfY29ycwoKYV93b3JkX2NvcnMgJT4lCiAgZmlsdGVyKGl0ZW0xICVpbiUgYygicGl4ZWwiLCAiY2FtZXJhIiwgImJhdHRlcnkiLCAiYW1wIiwgInByaWNlIiwgImNhc2UiLCAiZ3JlZW4iKSkgJT4lCiAgZ3JvdXBfYnkoaXRlbTEpICU+JQogIHNsaWNlX21heChjb3JyZWxhdGlvbiwgbiA9IDYpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBtdXRhdGUoaXRlbTIgPSByZW9yZGVyKGl0ZW0yLCBjb3JyZWxhdGlvbikpICU+JQogIGdncGxvdChhZXMoaXRlbTIsIGNvcnJlbGF0aW9uKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgZmFjZXRfd3JhcCh+IGl0ZW0xLCBzY2FsZXMgPSAiZnJlZSIpICsKICBjb29yZF9mbGlwKCkKCmFfd29yZF9jb3JzICU+JQogIGZpbHRlcihpdGVtMSAlaW4lIGMoImF2YWlsYWJsZSIsICJidXkiLCJ3aW4iLCAiZnJlZSIsInN0aWxsIiwibm93IiwgImdvb2QiLCAiYmV0dGVyIiwgImJlc3QiLCAibGlrZSIsIndpbGwiLCAiZ2V0IiwgIndhbnQiLCAibmVlZCIsICJjYW4iKSkgJT4lCiAgZ3JvdXBfYnkoaXRlbTEpICU+JQogIHNsaWNlX21heChjb3JyZWxhdGlvbiwgbiA9IDYpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBtdXRhdGUoaXRlbTIgPSByZW9yZGVyKGl0ZW0yLCBjb3JyZWxhdGlvbikpICU+JQogIGdncGxvdChhZXMoaXRlbTIsIGNvcnJlbGF0aW9uKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgZmFjZXRfd3JhcCh+IGl0ZW0xLCBzY2FsZXMgPSAiZnJlZSIpICsKICBjb29yZF9mbGlwKCkKCgpgYGAKCmBgYHtyIENvcnJlbGF0aW9uQXBwbGUsIGVjaG89RkFMU0V9CmFfd29yZF9jb3JzICU+JQogIGZpbHRlcihjb3JyZWxhdGlvbiA+IC4yOCkgJT4lCiAgZ3JhcGhfZnJvbV9kYXRhX2ZyYW1lKCkgJT4lCiAgZ2dyYXBoKGxheW91dCA9ICJmciIpICsKICBnZW9tX2VkZ2VfbGluayhhZXMoZWRnZV9hbHBoYSA9IGNvcnJlbGF0aW9uKSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIGdlb21fbm9kZV9wb2ludChjb2xvciA9ICJsaWdodGJsdWUiLCBzaXplID0gNSkgKwogIGdlb21fbm9kZV90ZXh0KGFlcyhsYWJlbCA9IG5hbWUpLCByZXBlbCA9IFRSVUUpICsKICB0aGVtZV92b2lkKCkKYGBgCgojIyBDbHVzdGVyaW5nCgpgYGB7ciBDbHVzdGVyaW5nIFNhbXN1bmd9CnRkbV9zIDwtIGNvcnB1czwtIENvcnB1cyhWZWN0b3JTb3VyY2Uod29yZF9zKSkgCnRkbV9zIDwtIFRlcm1Eb2N1bWVudE1hdHJpeCh0ZG1fcykKdGRtX3MyIDwtIHJlbW92ZVNwYXJzZVRlcm1zKHRkbV9zLCBzcGFyc2UgPSAwLjk1KQptczIgPC0gYXMubWF0cml4KHRkbV9zMikKIyBjbHVzdGVyIHRlcm1zCmRpc3RNYXRyaXhfcyA8LSBkaXN0KHNjYWxlKG1zMikpCmZpdF9zIDwtIGhjbHVzdChkaXN0TWF0cml4X3MsIG1ldGhvZCA9ICJ3YXJkLkQiKQpwbG90KGZpdF9zKQpyZWN0LmhjbHVzdChmaXRfcywgayA9IDYsYm9yZGVyID0gInJlZCIpICMgY3V0IHRyZWUgaW50byA2IGNsdXN0ZXJzCmBgYAoKYGBge3IgQ2x1c3RlcmluZyBBcHBsZX0KdGRtX2EgPC0gY29ycHVzPC0gQ29ycHVzKFZlY3RvclNvdXJjZSh3b3JkX2EpKSAKdGRtX2EgPC0gVGVybURvY3VtZW50TWF0cml4KHRkbV9hKQp0ZG1fYTIgPC0gcmVtb3ZlU3BhcnNlVGVybXModGRtX2EsIHNwYXJzZSA9IDAuOTUpCm1hMiA8LSBhcy5tYXRyaXgodGRtX2EyKQojIGNsdXN0ZXIgdGVybXMKZGlzdE1hdHJpeF9hIDwtIGRpc3Qoc2NhbGUobWEyKSkKZml0X2EgPC0gaGNsdXN0KGRpc3RNYXRyaXhfYSwgbWV0aG9kID0gIndhcmQuRCIpCnBsb3QoZml0X2EpCnJlY3QuaGNsdXN0KGZpdF9hLCBrID0gNixib3JkZXIgPSAicmVkIikgIyBjdXQgdHJlZSBpbnRvIDYgY2x1c3RlcnMKYGBgCgojIyBMREEgVG9waWMgTW9kZWxsaW5nCgpgYGB7ciBMREEgQmFzaWNzLCBpbmNsdWRlPUZBTFNFfQpvcHRpb25zKG1jLmNvcmVzID0gMTApCnRtX3BhckxhcHBseV9lbmdpbmUocGFyYWxsZWw6Om1jbGFwcGx5KSAgIyBtY2xhcHBseSBnZXRzIHRoZSBudW1iZXIgb2YgY29yZXMgZnJvbSBnbG9iYWwgb3B0aW9ucwoKYGBgCgojIyMgU2Ftc3VuZyBTMjIKCmBgYHtyIExEQSBTYW1zdW5nLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojIENyZWF0ZSBjb3JwdXMgb2JqZWN0CnNfY29ycHVzIDwtIENvcnB1cyhWZWN0b3JTb3VyY2UoYmdfZGZfcykpICAKCiMgUmVtb3ZlIEVuZ2xpc2ggc3RvcCB3b3Jkcy4Kc19jb3JwdXMgPC0gdG1fbWFwKHNfY29ycHVzLCByZW1vdmVXb3Jkcywgc3RvcHdvcmRzKCJlbiIpKSAgCgojIFJlbW92ZSBudW1iZXJzLgpzX2NvcnB1cyA8LSB0bV9tYXAoc19jb3JwdXMsIHJlbW92ZU51bWJlcnMpCgojIFN0ZW0gdGhlIHdvcmRzLgpzX2NvcnB1cyA8LSB0bV9tYXAoc19jb3JwdXMsIHN0ZW1Eb2N1bWVudCkKCiMgUmVtb3ZlIHRoZSBzdGVtcyBhc3NvY2lhdGVkIHdpdGggb3VyIHNlYXJjaCB0ZXJtcyEKc19jb3JwdXMgPC0gdG1fbWFwKHNfY29ycHVzLCByZW1vdmVXb3JkcywgYygiZ2FsYXhpIiwgInNhbXN1bmciLCAiZ2FsYXh5IiwgInVsdHJhIiwgIlwic2Ftc3VuZyIsICJcImdhbGF4eSIsICJpcGhvbmUiLCAiaXBob24iLCAiXCJpcGhvbiIsICJhcHBsIiwgInBybyIsICJtYXgiKSkKCnNfZG9jLmxlbmd0aHMgPC0gcm93U3Vtcyhhcy5tYXRyaXgoRG9jdW1lbnRUZXJtTWF0cml4KHNfY29ycHVzKSkpCnNfZHRtIDwtIERvY3VtZW50VGVybU1hdHJpeChzX2NvcnB1cykKCiMgTm93IGZvciBzb21lIHRvcGljcwpTRUVEID0gc2FtcGxlKDE6MTAwMDAwMCwgMSkgICMgUGljayBhIHJhbmRvbSBzZWVkIGZvciByZXBsaWNhdGlvbgprID0gNSAKCiMgVGhpcyBtaWdodCB0YWtlIGEgbWludXRlIQpzX21vZGVscyA8LSBsaXN0KAogIENUTSAgICAgICA9IENUTShzX2R0bSwgayA9IGssIGNvbnRyb2wgPSBsaXN0KHNlZWQgPSBTRUVELCB2YXIgPSBsaXN0KHRvbCA9IDEwXi00KSwgZW0gPSBsaXN0KHRvbCA9IDEwXi0zKSkpLAogIFZFTSAgICAgICA9IExEQShzX2R0bSwgayA9IGssIGNvbnRyb2wgPSBsaXN0KHNlZWQgPSBTRUVEKSksCiAgVkVNX0ZpeGVkID0gTERBKHNfZHRtLCBrID0gaywgY29udHJvbCA9IGxpc3QoZXN0aW1hdGUuYWxwaGEgPSBGQUxTRSwgc2VlZCA9IFNFRUQpKSwKICBHaWJicyAgICAgPSBMREEoc19kdG0sIGsgPSBrLCBtZXRob2QgPSAiR2liYnMiLCBjb250cm9sID0gbGlzdChzZWVkID0gU0VFRCwgYnVybmluID0gMTAwMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpbiA9IDEwMCwgICAgaXRlciA9IDEwMDApKQopCgojIFRoZXJlIHlvdSBoYXZlIGl0LiBNb2RlbHMgbm93IGhvbGRzIDQgdG9waWNzLiBTZWUgdGhlIHRvcGljbW9kZWxzIEFQSSBkb2N1bWVudGF0aW9uIGZvciBkZXRhaWxzCgojIFRvcCAxMCB0ZXJtcyBvZiBlYWNoIHRvcGljIGZvciBlYWNoIG1vZGVsCiMgRG8geW91IHNlZSBhbnkgdGhlbWVzIHlvdSBjYW4gbGFiZWwgdG8gdGhlc2UgInRvcGljcyIgKGxpc3RzIG9mIHdvcmRzKT8KbGFwcGx5KHNfbW9kZWxzLCB0ZXJtcywgMTApCgpzX2Fzc2lnbm1lbnRzIDwtIHNhcHBseShzX21vZGVscywgdG9waWNzKSAKCnNfYXNzaWdubWVudHMKCgojIyMgc3RpbGwgbWlzc2luZzogZ3JhcGhzIGRlcGljdCB0aGUgcHJvYmFiaWxpdHkgZGlzdHJpYnV0aW9ucyBmb3IgYWxsIHRoZSB0ZXJtcyBlYWNoIExEQSB0b3BpYyBoYXMgMTAgdGVybXMgd2hpY2ggaXMgaW5kZXBlbmRlbnQgb2YgdGVybXMgaW4gb3RoZXIgTERBIHRvcGljCmBgYAoKVGhlIHRvcGljcyBhYm91dCAic2VyaSIsICJub3ciLCAiY2FtZXJhIiwgInVwZGF0ZSIgcmVsYXRlcyB0byB0aGUgW1MyMiBVbHRyYSdzIEFwcmlsIHBhdGNoIHRoYXQgaW50cm9kdWNlZCBtYW55IGNhbWVyYS1yZWxhdGVkIGZlYXR1cmVzXShodHRwczovL3d3dy5hbmRyb2lkcG9saWNlLmNvbS9zYW1zdW5ncy1hcHJpbC0yMDIyLXNlY3VyaXR5LXVwZGF0ZS1pcy1hcnJpdmluZy1mb3ItZ2FsYXh5LW93bmVycy1pbi10aGUtdXMvKS4KCiMjIyBBcHBsZSBpUGhvbmUgMTMKCmBgYHtyIExEQSBBcHBsZSwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KIyBDcmVhdGUgY29ycHVzIG9iamVjdAphX2NvcnB1cyA8LSBDb3JwdXMoVmVjdG9yU291cmNlKGJnX2RmX2EpKSAgCgojIFJlbW92ZSBFbmdsaXNoIHN0b3Agd29yZHMuCmFfY29ycHVzIDwtIHRtX21hcChhX2NvcnB1cywgcmVtb3ZlV29yZHMsIHN0b3B3b3JkcygiZW4iKSkgIAoKIyBSZW1vdmUgbnVtYmVycy4KYV9jb3JwdXMgPC0gdG1fbWFwKGFfY29ycHVzLCByZW1vdmVOdW1iZXJzKQoKIyBTdGVtIHRoZSB3b3Jkcy4KYV9jb3JwdXMgPC0gdG1fbWFwKGFfY29ycHVzLCBzdGVtRG9jdW1lbnQpCgojIFJlbW92ZSB0aGUgc3RlbXMgYXNzb2NpYXRlZCB3aXRoIG91ciBzZWFyY2ggdGVybXMhCmFfY29ycHVzIDwtIHRtX21hcChhX2NvcnB1cywgcmVtb3ZlV29yZHMsIGMoImdhbGF4aSIsICJzYW1zdW5nIiwgImdhbGF4eSIsICJ1bHRyYSIsICJcInNhbXN1bmciLCAiXCJnYWxheHkiLCAiaXBob25lIiwgImlwaG9uIiwgIlwiaXBob24iLCAiYXBwbCIsICJwcm8iLCAibWF4IikpCgphX2RvYy5sZW5ndGhzIDwtIHJvd1N1bXMoYXMubWF0cml4KERvY3VtZW50VGVybU1hdHJpeChhX2NvcnB1cykpKQphX2R0bSA8LSBEb2N1bWVudFRlcm1NYXRyaXgoYV9jb3JwdXMpCgojIE5vdyBmb3Igc29tZSB0b3BpY3MKU0VFRCA9IHNhbXBsZSgxOjEwMDAwMDAsIDEpIAprID0gMTAKCiMgVGhpcyBtaWdodCB0YWtlIGEgbWludXRlIQphX21vZGVscyA8LSBsaXN0KAogIENUTSAgICAgICA9IENUTShhX2R0bSwgayA9IGssIGNvbnRyb2wgPSBsaXN0KHNlZWQgPSBTRUVELCB2YXIgPSBsaXN0KHRvbCA9IDEwXi00KSwgZW0gPSBsaXN0KHRvbCA9IDEwXi0zKSkpLAogIFZFTSAgICAgICA9IExEQShhX2R0bSwgayA9IGssIGNvbnRyb2wgPSBsaXN0KHNlZWQgPSBTRUVEKSksCiAgVkVNX0ZpeGVkID0gTERBKGFfZHRtLCBrID0gaywgY29udHJvbCA9IGxpc3QoZXN0aW1hdGUuYWxwaGEgPSBGQUxTRSwgc2VlZCA9IFNFRUQpKSwKICBHaWJicyAgICAgPSBMREEoYV9kdG0sIGsgPSBrLCBtZXRob2QgPSAiR2liYnMiLCBjb250cm9sID0gbGlzdChzZWVkID0gU0VFRCwgYnVybmluID0gMTAwMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGluID0gMTAwLCAgICBpdGVyID0gMTAwMCkpCikKCiMgVG9wIDEwIHRlcm1zIG9mIGVhY2ggdG9waWMgZm9yIGVhY2ggbW9kZWwKIyBEbyB5b3Ugc2VlIGFueSB0aGVtZXMgeW91IGNhbiBsYWJlbCB0byB0aGVzZSAidG9waWNzIiAobGlzdHMgb2Ygd29yZHMpPwpsYXBwbHkoYV9tb2RlbHMsIHRlcm1zLCAxMCkKCmFfYXNzaWdubWVudHMgPC0gc2FwcGx5KGFfbW9kZWxzLCB0b3BpY3MpIAoKYV9hc3NpZ25tZW50cwoKCiMjIyBzdGlsbCBtaXNzaW5nOiBncmFwaHMgZGVwaWN0IHRoZSBwcm9iYWJpbGl0eSBkaXN0cmlidXRpb25zIGZvciBhbGwgdGhlIHRlcm1zIGVhY2ggTERBIHRvcGljIGhhcyAxMCB0ZXJtcyB3aGljaCBpcyBpbmRlcGVuZGVudCBvZiB0ZXJtcyBpbiBvdGhlciBMREEgdG9waWMKYGBgCgojIEFtYXpvbiBSZXZpZXcgQW5hbHlzaXMKCkZvciBmdXJ0aGVyIGFuYWx5c2lzLCB3ZSBoYXZlIGRlY2lkZWQgdG8gYW5hbHlzZSB0aGUgQW1hem9uIHByb2R1Y3QgcmV2aWV3cyBmb3IgYm90aCB0aGUgcGhvbmVzIGluIG9yZGVyIHRvIHVuZGVyc3RhbmQgaWYgdGhlIHNlbnRpbWVudHMgb2YgY3VzdG9tZXJzIG9uIFR3aXR0ZXIgYW5kIEFtYXpvbiB3ZXJlIG1hdGNoaW5nIG9yIG5vdC4KClRvIGRvIHRoaXMsIHRoZSBmaXJzdCBzdGVwIHdhcyB0byBjb2xsZWN0IHRoZSBkYXRhLiBXZSBmYWNlZCBhIHNpbWlsYXIgc2l0dWF0aW9uIGZvciBjb2xsZWN0aW5nIHRoZSBkYXRhLCBTYW1zdW5nIFMyMiBoYWQgdmVyeSBmZXcgcmV2aWV3cyBhbmQgdGhlIGlQaG9uZSAxMyBoYWQgYSBsYXJnZSBhbW91bnQgb2YgcmV2aWV3cy4gU28sIHRvIGNvbGxlY3QgbW9yZSBkYXRhLCB3ZSB1c2VkIEFtYXpvbiByZXZpZXdzIGZyb20gZGlmZmVyZW50IGNvdW50cnkgd2Vic2l0ZXMgbGlrZSBVSywgSW5kaWEsIFVTQSBhbmQgQXVzdHJhbGlhLiBTcGVjaWZpY2FsbHksIEVuZ2xpc2ggcmV2aWV3cyB3ZXJlIHNlbGVjdGVkIHRvIHByb2NlZWQgd2l0aCB0aGUgYW5hbHlzaXMuCgpUaGUgZm9sbG93aW5nIFIgY29kZSB3YXMgaW1wbGVtZW50ZWQgdG8gY29sbGVjdCBkYXRhIGZyb20gZGlmZmVyZW50IEFtYXpvbiB3ZWJzaXRlcy4gKFs8aHR0cHM6Ly9tYXJ0aW5jdGMuZ2l0aHViLmlvL2Jsb2cvdmlnbmV0dGUtc2NyYXBpbmctYW1hem9uLXJldmlld3MtaW4tci8+XShodHRwczovL21hcnRpbmN0Yy5naXRodWIuaW8vYmxvZy92aWduZXR0ZS1zY3JhcGluZy1hbWF6b24tcmV2aWV3cy1pbi1yLyl7LnVyaX0pCgpgYGB7ciBJbml0aWFsaXNpbmcgUGFja2FnZXMgQW1hem9uLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQpsaWJyYXJ5KHJlYWR4bCkKbGlicmFyeSh0d2l0dGVSKQpsaWJyYXJ5KFJPQXV0aCkKbGlicmFyeShobXMpCmxpYnJhcnkobHVicmlkYXRlKSAKbGlicmFyeSh0aWR5dGV4dCkKbGlicmFyeShOTFApCmxpYnJhcnkodG0pCmxpYnJhcnkoUkNvbG9yQnJld2VyKQpsaWJyYXJ5KHdvcmRjbG91ZCkKbGlicmFyeShpZ3JhcGgpCmxpYnJhcnkoZ2x1ZSkKbGlicmFyeShzY2FsZXMpCmxpYnJhcnkobmV0d29ya0QzKQpsaWJyYXJ5KHJ0d2VldCkKbGlicmFyeShwbHlyKQpsaWJyYXJ5KHN0cmluZ3IpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShnZ2Vhc3kpCmxpYnJhcnkocGxvdGx5KQpsaWJyYXJ5KGRwbHlyKSAgCmxpYnJhcnkoaG1zKQpsaWJyYXJ5KGx1YnJpZGF0ZSkgCmxpYnJhcnkobWFncml0dHIpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHdpZHlyKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KHRpZHl0ZXh0KQpsaWJyYXJ5KGJhc2U2NGVuYykKYGBgCgojIyBEYXRhIFNjcmFwaW5nIGZyb20gQW1hem9uCgpgYGB7cn0KIyAjU2NyYXBpbmcgUHJvZHVjdCBSZXZpZXdzIGZyb20gQW1hem9uCiMgCiMgI2ltcG9ydCBsaWJyYXJpZXMKIyBsaWJyYXJ5KHJ2ZXN0KQojIGxpYnJhcnkoc3RyaW5ncikKIyBsaWJyYXJ5KHhtbDIpCiMgbGlicmFyeSh0aWR5dmVyc2UpCiMgCiMgCiMgc2NyYXBlX2FtYXpvbiA8LSBmdW5jdGlvbihBU0lOLCBwYWdlX251bSl7CiMgICAKIyAgICNhbWF6b25fdWsKIyAgICN1cmxfcmV2aWV3cyA8LSBwYXN0ZTAoImh0dHBzOi8vd3d3LmFtYXpvbi5jby51ay9wcm9kdWN0LXJldmlld3MvIixBU0lOLCIvP3BhZ2VOdW1iZXI9IixwYWdlX251bSkKIyAgICNhbWF6b24uY29tCiMgICAjdXJsX3Jldmlld3MgPC0gcGFzdGUwKCJodHRwczovL3d3dy5hbWF6b24uY29tL3Byb2R1Y3QtcmV2aWV3cy8iLEFTSU4sIi8/cGFnZU51bWJlcj0iLHBhZ2VfbnVtKQojICAgI2FtYXpvbi5pbgojICAgI3VybF9yZXZpZXdzIDwtIHBhc3RlMCgiaHR0cHM6Ly93d3cuYW1hem9uLmluL3Byb2R1Y3QtcmV2aWV3cy8iLEFTSU4sIi8/cGFnZU51bWJlcj0iLHBhZ2VfbnVtKQojICAgCiMgICAjYW1hem9uLmNvbS5hdQojICAgdXJsX3Jldmlld3MgPC0gcGFzdGUwKCJodHRwczovL3d3dy5hbWF6b24uY29tLmF1L3Byb2R1Y3QtcmV2aWV3cy8iLEFTSU4sIi8/cGFnZU51bWJlcj0iLHBhZ2VfbnVtKQojICAgCiMgICBkb2MgPC0gcmVhZF9odG1sKHVybF9yZXZpZXdzKSAjIEFzc2lnbiByZXN1bHRzIHRvIGBkb2NgCiMgICAKIyAgICMgUmV2aWV3IFRpdGxlCiMgICBkb2MgJT4lIAojICAgICBodG1sX25vZGVzKCJbY2xhc3M9J2Etc2l6ZS1iYXNlIGEtbGluay1ub3JtYWwgcmV2aWV3LXRpdGxlIGEtY29sb3ItYmFzZSByZXZpZXctdGl0bGUtY29udGVudCBhLXRleHQtYm9sZCddIikgJT4lCiMgICAgIGh0bWxfdGV4dCgpIC0+IHJldmlld190aXRsZTEKIyAgIAojICAgcmV2aWV3X3RpdGxlIDwtIHN0cl9zcXVpc2gocmV2aWV3X3RpdGxlMSkKIyAgIAojICAgIyBSZXZpZXcgVGV4dAojICAgZG9jICU+JSAKIyAgICAgaHRtbF9ub2RlcygiW2NsYXNzPSdhLXNpemUtYmFzZSByZXZpZXctdGV4dCByZXZpZXctdGV4dC1jb250ZW50J10iKSAlPiUKIyAgICAgaHRtbF90ZXh0KCkgLT4gcmV2aWV3X3RleHQxCiMgICAKIyAgIHJldmlld190ZXh0IDwtIHN0cl9zcXVpc2gocmV2aWV3X3RleHQxKQojICAgCiMgICAjIE51bWJlciBvZiBzdGFycyBpbiByZXZpZXcKIyAgIGRvYyAlPiUKIyAgICAgaHRtbF9ub2RlcygiW2RhdGEtaG9vaz0ncmV2aWV3LXN0YXItcmF0aW5nJ10iKSAlPiUKIyAgICAgaHRtbF90ZXh0KCkgLT4gcmV2aWV3X3N0YXIxCiMgICAKIyAgIHJldmlld19zdGFyIDwtIHN0cl9zcXVpc2gocmV2aWV3X3N0YXIxKQojICAgCiMgICAjIERhdGUgCiMgICAKIyAgIGRvYyAlPiUKIyAgICAgaHRtbF9ub2RlcygiW2RhdGEtaG9vaz0ncmV2aWV3LWRhdGUnXSIpICU+JQojICAgICBodG1sX3RleHQoKSAtPiByZXZpZXdfZGF0ZTEKIyAgIHJldmlld19kYXRlIDwtIHN0cl9zcXVpc2gocmV2aWV3X2RhdGUxKQojICAgCiMgICAjIFJldHVybiBhIHRpYmJsZQojICB0aWJibGUocmV2aWV3X3RpdGxlLAojICAgICAgICAgIHJldmlld190ZXh0LAojICAgICAgICAgIHJldmlld19zdGFyLAojICAgICAgICAgIHJldmlld19kYXRlLAojICAgICAgICAgIHBhZ2UgPSBwYWdlX251bSkgJT4lIHJldHVybigpCiMgfQojIAojIAojIEFTSU4gPC0gIkIwOU1XMTdKUVkiICMgU3BlY2lmeSBBU0lOCiMgcGFnZV9yYW5nZSA8LSAxICMgTGV0J3Mgc2F5IHdlIHdhbnQgdG8gc2NyYXBlIHBhZ2VzIDEgdG8gMTAKIyAKIyBtYXRjaF9rZXkgPC0gdGliYmxlKG4gPSBwYWdlX3JhbmdlLAojICAgICAgICAgICAgICAgICAgICAga2V5ID0gc2FtcGxlKHBhZ2VfcmFuZ2UsbGVuZ3RoKHBhZ2VfcmFuZ2UpKSkKIyAKIyBsYXBwbHkocGFnZV9yYW5nZSwgZnVuY3Rpb24oaSl7CiMgICBqIDwtIG1hdGNoX2tleVttYXRjaF9rZXkkbj09aSxdJGtleQojICAgCiMgICBtZXNzYWdlKCJHZXR0aW5nIHBhZ2UgIixpLCAiIG9mICIsbGVuZ3RoKHBhZ2VfcmFuZ2UpLCAiOyBBY3R1YWw6IHBhZ2UgIixqKSAjIFByb2dyZXNzIGJhcgojICAgCiMgICBTeXMuc2xlZXAoMykgIyBUYWtlIGEgdGhyZWUgc2Vjb25kIGJyZWFrCiMgICAKIyAgIGlmKChpICUlIDMpID09IDApeyAjIEFmdGVyIGV2ZXJ5IHRocmVlIHNjcmFwZXMuLi4gdGFrZSBhbm90aGVyIHR3byBzZWNvbmQgYnJlYWsKIyAgICAgCiMgICAgIG1lc3NhZ2UoIlRha2luZyBhIGJyZWFrLi4uIikgIyBQcmludHMgYSAndGFraW5nIGEgYnJlYWsnIG1lc3NhZ2Ugb24geW91ciBjb25zb2xlCiMgICAgIAojICAgICBTeXMuc2xlZXAoMikgIyBUYWtlIGFuIGFkZGl0aW9uYWwgdHdvIHNlY29uZCBicmVhawojICAgfQojICAgc2NyYXBlX2FtYXpvbihBU0lOID0gQVNJTiwgcGFnZV9udW0gPSBqKSAjIFNjcmFwZQojIH0pIC0+IG91dHB1dF9saXN0CiMgCiMgCiMgd3JpdGUuY3N2KG91dHB1dF9saXN0LCJDOlxcVXNlcnNcXFNocnV0aGlcXE9uZURyaXZlXFxEb2N1bWVudHNcXFNlbWVzdGVyIDJcXFNvY2lhbCBNZWRpYSBBbmFseXRpY3NcXEdyb3VwIEFzc2lnbm1lbnRcXFNhbXN1bmdfQXVzdHJhbGlhLmNzdiIscm93Lm5hbWVzID0gRkFMU0UpCgpgYGAKCiMjIERhdGEgSW5wdXQKCmBgYHtyIFJlYWQgZmlsZSBTYW1zdW5nLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQpzYW1zdW5nLnJldmlld3MgPC0gcmVhZC5jc3YoIlNhbXN1bmdfQW16LmNzdiIpCmlwaG9uZS5yZXZpZXdzIDwtIHJlYWQuY3N2KCJpUGhvbmVfQW16LmNzdiIpCmBgYAoKYGBge3IgSW5mb3JtYXRpb24gYWJvdXQgdGhlIGRhdGEsIGVjaG89RkFMU0V9CmRpbShzYW1zdW5nLnJldmlld3MpICNkaW1lbnNpb24gb2YgdGhlIGRhdGEKc3VtbWFyeShzYW1zdW5nLnJldmlld3MpCmRpbShpcGhvbmUucmV2aWV3cykKc3VtbWFyeShpcGhvbmUucmV2aWV3cykKYGBgCgojIyBEYXRhIFByZXByb2Nlc3NpbmcKCmBgYHtyIFByZXByb2Nlc3NpbmcgQW1hem9uIGRhdGEsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CiMgTG9hZCAiU3RvcCBXb3JkcyIgZnJvbSB0aGUgdGlkeXRleHQgcGFja2FnZQpkYXRhKCJzdG9wX3dvcmRzIikKCiMgUmVtb3ZpbmcgU3RvcCBXb3JkcyBpbiBib3RoIGRhdGEgZnJhbWVzCnNhbXN1bmcucmV2aWV3cy50ZXh0IDwtIHNhbXN1bmcucmV2aWV3cyAlPiUKICBzZWxlY3QocmV2aWV3X3RleHQpCgppcGhvbmUucmV2aWV3cy50ZXh0IDwtIGlwaG9uZS5yZXZpZXdzICU+JQogIHNlbGVjdChyZXZpZXdfdGV4dCkKCmxpYnJhcnkoc3RyaW5naSkKc3RyaV9lbmNfbWFyayhzYW1zdW5nLnJldmlld3MudGV4dCRyZXZpZXdfdGV4dCkKc2Ftc3VuZy5yZXZpZXdzLnRleHQkcmV2aWV3X3RleHQgPC0gc2FwcGx5KHNhbXN1bmcucmV2aWV3cy50ZXh0JHJldmlld190ZXh0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbihyb3cpIGljb252KHJvdywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAibGF0aW4xIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQVNDSUkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1YiA9ICIgIikpCgojIExvd2VjYXNlIGFsbCB0ZXh0CnNhbXN1bmcucmV2aWV3cy50ZXh0JHJldmlld190ZXh0IDwtIHRvbG93ZXIoc2Ftc3VuZy5yZXZpZXdzLnRleHQkcmV2aWV3X3RleHQpCgojIG1ha2Ugd2Fzbid0PXdhcyBub3QsIGNhbid0PWNhbiBub3QsIGV0Yy4uCnNhbXN1bmcucmV2aWV3cy50ZXh0JHJldmlld190ZXh0IDwtIGdzdWIoIndhc25bXHUyMDE5J110IiwgIndhcyBub3QiLCBzYW1zdW5nLnJldmlld3MudGV4dCRyZXZpZXdfdGV4dCkKc2Ftc3VuZy5yZXZpZXdzLnRleHQkcmV2aWV3X3RleHQgPC0gZ3N1Yigid29uW1x1MjAxOSdddCIsICJ3aWxsIG5vdCIsIHNhbXN1bmcucmV2aWV3cy50ZXh0JHJldmlld190ZXh0KQpzYW1zdW5nLnJldmlld3MudGV4dCRyZXZpZXdfdGV4dCA8LSBnc3ViKCJjYW5bXHUyMDE5J110IiwgImNhbiBub3QiLCBzYW1zdW5nLnJldmlld3MudGV4dCRyZXZpZXdfdGV4dCkKc2Ftc3VuZy5yZXZpZXdzLnRleHQkcmV2aWV3X3RleHQgPC0gZ3N1YigiZGlkbltcdTIwMTknXXQiLCAiZGlkIG5vdCIsIHNhbXN1bmcucmV2aWV3cy50ZXh0JHJldmlld190ZXh0KQpzYW1zdW5nLnJldmlld3MudGV4dCRyZXZpZXdfdGV4dCA8LSBnc3ViKCJkb25bXHUyMDE5J110IiwgImRvIG5vdCIsIHNhbXN1bmcucmV2aWV3cy50ZXh0JHJldmlld190ZXh0KQpzYW1zdW5nLnJldmlld3MudGV4dCRyZXZpZXdfdGV4dCA8LSBnc3ViKCJJW1x1MjAxOSddbSIsICJJIGFtIiwgc2Ftc3VuZy5yZXZpZXdzLnRleHQkcmV2aWV3X3RleHQpCnNhbXN1bmcucmV2aWV3cy50ZXh0JHJldmlld190ZXh0IDwtIGdzdWIoIltcdTIwMTknXXZlIiwgIiBoYXZlIiwgc2Ftc3VuZy5yZXZpZXdzLnRleHQkcmV2aWV3X3RleHQpIApzYW1zdW5nLnJldmlld3MudGV4dCRyZXZpZXdfdGV4dCA8LSBnc3ViKCJbXHUyMDE5fCddcyIsICIiLCBzYW1zdW5nLnJldmlld3MudGV4dCRyZXZpZXdfdGV4dCkKc2Ftc3VuZy5yZXZpZXdzLnRleHQkcmV2aWV3X3RleHQgPC0gZ3N1YigiW1x1MjAxOSddcmUiLCAiIGFyZSIsIHNhbXN1bmcucmV2aWV3cy50ZXh0JHJldmlld190ZXh0KQpzYW1zdW5nLnJldmlld3MudGV4dCRyZXZpZXdfdGV4dCA8LSBnc3ViKCJbXHUyMDE5J11sbCIsICIgd2lsbCIsIHNhbXN1bmcucmV2aWV3cy50ZXh0JHJldmlld190ZXh0KQoKCiMgSWYgeW91IHZpZXcgY29tbW9uIHR5cG9zIGR1cmluZyB5b3VyIGFuYWx5c2lzLCBmaXggdGhlbSBoZXJlLgpzYW1zdW5nLnJldmlld3MudGV4dCRyZXZpZXdfdGV4dDwtIGdzdWIoImNhbmNlbGluZyIsICJjYW5jZWxsaW5nIiwgc2Ftc3VuZy5yZXZpZXdzLnRleHQkcmV2aWV3X3RleHQpCnNhbXN1bmcucmV2aWV3cy50ZXh0JHJldmlld190ZXh0IDwtIGdzdWIoImNhbmNlbGxhdGlvbiIsICJjYW5jZWxsaW5nIiwgc2Ftc3VuZy5yZXZpZXdzLnRleHQkcmV2aWV3X3RleHQpCnNhbXN1bmcucmV2aWV3cy50ZXh0JHJldmlld190ZXh0IDwtIGdzdWIoImlzc3VlcyIsICJpc3N1ZSIsIHNhbXN1bmcucmV2aWV3cy50ZXh0JHJldmlld190ZXh0KQoKIyBvbWl0IHRoZSBmb2xsb3dpbmcgdHdvIGxpbmVzIGlmIHlvdSBoYXZlIG5vdCBsb2FkZWQgdGhlIHRtIHBhY2thZ2UKIyBSZW1vdmUgbnVtYmVycyBpbiB0aGUgdGV4dAojYm9zZS5oZWFkcGhvbmVzLnJldmlld3MudGV4dCRyZXZpZXdfdGV4dCA8LSByZW1vdmVOdW1iZXJzKGJvc2UuaGVhZHBob25lcy5yZXZpZXdzLnRleHQkcmV2aWV3X3RleHQpCgojIFJlbW92ZSBwdW5jdHVhdGlvbnMgaW4gdGhlIHRleHQKc2Ftc3VuZy5yZXZpZXdzLnRleHQkcmV2aWV3X3RleHQgPC0gcmVtb3ZlUHVuY3R1YXRpb24oc2Ftc3VuZy5yZXZpZXdzLnRleHQkcmV2aWV3X3RleHQpCgojIEZpeCBOZWdhdGlvbnMKIyBDcmVhdGUgYSBsaXN0IHRvIGlkZW50aWZ5IHRoZSBzZW50aW1lbnQgc2hpZnRlcnMgaW4gdGhlIHRleHQKbmVnYXRpb24ud29yZHMgPC0gYygibm90IiwKICAgICAgICAgICAgICAgICAgICAibm8iLAogICAgICAgICAgICAgICAgICAgICJ3aXRob3V0IiwKICAgICAgICAgICAgICAgICAgICAibmV2ZXIiLAogICAgICAgICAgICAgICAgICAgICJiYWQiLAogICAgICAgICAgICAgICAgICAgICJub25lIiwKICAgICAgICAgICAgICAgICAgICAibmV2ZXIiLAogICAgICAgICAgICAgICAgICAgICJub2JvZHkiLAogICAgICAgICAgICAgICAgICAgICJub3doZXJlIiwKICAgICAgICAgICAgICAgICAgICAibmVpdGhlciIsCiAgICAgICAgICAgICAgICAgICAgIm5vdGhpbmciCikKCnN0cmlfZW5jX21hcmsoaXBob25lLnJldmlld3MudGV4dCRyZXZpZXdfdGV4dCkKaXBob25lLnJldmlld3MudGV4dCRyZXZpZXdfdGV4dCA8LSBzYXBwbHkoaXBob25lLnJldmlld3MudGV4dCRyZXZpZXdfdGV4dCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbihyb3cpIGljb252KHJvdywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJsYXRpbjEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkFTQ0lJIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1YiA9ICIgIikpCgojIExvd2VjYXNlIGFsbCB0ZXh0CmlwaG9uZS5yZXZpZXdzLnRleHQkcmV2aWV3X3RleHQgPC0gdG9sb3dlcihpcGhvbmUucmV2aWV3cy50ZXh0JHJldmlld190ZXh0KQoKIyBtYWtlIHdhc24ndD13YXMgbm90LCBjYW4ndD1jYW4gbm90LCBldGMuLgppcGhvbmUucmV2aWV3cy50ZXh0JHJldmlld190ZXh0IDwtIGdzdWIoIndhc25bXHUyMDE5J110IiwgIndhcyBub3QiLCBpcGhvbmUucmV2aWV3cy50ZXh0JHJldmlld190ZXh0KQppcGhvbmUucmV2aWV3cy50ZXh0JHJldmlld190ZXh0IDwtIGdzdWIoIndvbltcdTIwMTknXXQiLCAid2lsbCBub3QiLCBpcGhvbmUucmV2aWV3cy50ZXh0JHJldmlld190ZXh0KQppcGhvbmUucmV2aWV3cy50ZXh0JHJldmlld190ZXh0IDwtIGdzdWIoImNhbltcdTIwMTknXXQiLCAiY2FuIG5vdCIsIGlwaG9uZS5yZXZpZXdzLnRleHQkcmV2aWV3X3RleHQpCmlwaG9uZS5yZXZpZXdzLnRleHQkcmV2aWV3X3RleHQgPC0gZ3N1YigiZGlkbltcdTIwMTknXXQiLCAiZGlkIG5vdCIsIGlwaG9uZS5yZXZpZXdzLnRleHQkcmV2aWV3X3RleHQpCmlwaG9uZS5yZXZpZXdzLnRleHQkcmV2aWV3X3RleHQgPC0gZ3N1YigiZG9uW1x1MjAxOSdddCIsICJkbyBub3QiLCBpcGhvbmUucmV2aWV3cy50ZXh0JHJldmlld190ZXh0KQppcGhvbmUucmV2aWV3cy50ZXh0JHJldmlld190ZXh0IDwtIGdzdWIoIklbXHUyMDE5J11tIiwgIkkgYW0iLCBpcGhvbmUucmV2aWV3cy50ZXh0JHJldmlld190ZXh0KQppcGhvbmUucmV2aWV3cy50ZXh0JHJldmlld190ZXh0IDwtIGdzdWIoIltcdTIwMTknXXZlIiwgIiBoYXZlIiwgaXBob25lLnJldmlld3MudGV4dCRyZXZpZXdfdGV4dCkgCmlwaG9uZS5yZXZpZXdzLnRleHQkcmV2aWV3X3RleHQgPC0gZ3N1YigiW1x1MjAxOXwnXXMiLCAiIiwgaXBob25lLnJldmlld3MudGV4dCRyZXZpZXdfdGV4dCkKaXBob25lLnJldmlld3MudGV4dCRyZXZpZXdfdGV4dCA8LSBnc3ViKCJbXHUyMDE5J11yZSIsICIgYXJlIiwgaXBob25lLnJldmlld3MudGV4dCRyZXZpZXdfdGV4dCkKaXBob25lLnJldmlld3MudGV4dCRyZXZpZXdfdGV4dCA8LSBnc3ViKCJbXHUyMDE5J11sbCIsICIgd2lsbCIsIGlwaG9uZS5yZXZpZXdzLnRleHQkcmV2aWV3X3RleHQpCgoKIyBJZiB5b3UgdmlldyBjb21tb24gdHlwb3MgZHVyaW5nIHlvdXIgYW5hbHlzaXMsIGZpeCB0aGVtIGhlcmUuCmlwaG9uZS5yZXZpZXdzLnRleHQkcmV2aWV3X3RleHQ8LSBnc3ViKCJjYW5jZWxpbmciLCAiY2FuY2VsbGluZyIsIGlwaG9uZS5yZXZpZXdzLnRleHQkcmV2aWV3X3RleHQpCmlwaG9uZS5yZXZpZXdzLnRleHQkcmV2aWV3X3RleHQgPC0gZ3N1YigiY2FuY2VsbGF0aW9uIiwgImNhbmNlbGxpbmciLCBpcGhvbmUucmV2aWV3cy50ZXh0JHJldmlld190ZXh0KQoKIyBSZW1vdmUgcHVuY3R1YXRpb25zIGluIHRoZSB0ZXh0CmlwaG9uZS5yZXZpZXdzLnRleHQkcmV2aWV3X3RleHQgPC0gcmVtb3ZlUHVuY3R1YXRpb24oaXBob25lLnJldmlld3MudGV4dCRyZXZpZXdfdGV4dCkKCmBgYAoKYGBge3IgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0Kc2hpZnRlZC53b3JkcyA8LSBzYW1zdW5nLnJldmlld3MudGV4dCAlPiUKICB1bm5lc3RfdG9rZW5zKGJpZ3JhbSwgcmV2aWV3X3RleHQsIHRva2VuID0gIm5ncmFtcyIsIG4gPSAyKSU+JQogIGRwbHlyOjpjb3VudChiaWdyYW0sIHNvcnQgPSBUUlVFKSAlPiUKICBzZXBhcmF0ZShiaWdyYW0sIGMoIndvcmQxIiwgIndvcmQyIiksIHNlcCA9ICIgIiklPiUKICBmaWx0ZXIod29yZDEgJWluJSBuZWdhdGlvbi53b3JkcyAmICF3b3JkMiAlaW4lIHN0b3Bfd29yZHMkd29yZCklPiUKICBpbm5lcl9qb2luKGdldF9zZW50aW1lbnRzKCJiaW5nIiksIGJ5ID0gYyh3b3JkMiA9ICJ3b3JkIikpJT4lCiAgbXV0YXRlKHNlbnRpbWVudCA9IGlmZWxzZShzZW50aW1lbnQgPT0gInBvc2l0aXZlIiwgMSwgLTEpKSAlPiUKICBtdXRhdGUoc2NvcmUgPSBzZW50aW1lbnQgKiBuKSAlPiUKICBtdXRhdGUod29yZDIgPSByZW9yZGVyKHdvcmQyLCBzY29yZSkpCgpzaGlmdGVkLndvcmRzCgojIFBpY2sgdGhlIG1vc3QgZWZmZWN0aXZlIHNlbnRpbWVudCBzaGlmdGVycwpuZWdhdGVkLnBocmFzZXMgPC0gYygibm90IHdvcnRoIiwgCiAgICAgICAgICAgICAgICAgICAgICJub3Qgbm9pc2UiLAogICAgICAgICAgICAgICAgICAgICAibm8gaXNzdWVzIiwKICAgICAgICAgICAgICAgICAgICAgIm5vIGNvbXBsYWludHMiLAogICAgICAgICAgICAgICAgICAgICAibm90IGRpc2FwcG9pbnQiLAogICAgICAgICAgICAgICAgICAgICAibm90IGRpc2FwcG9pbnRlZCIsCiAgICAgICAgICAgICAgICAgICAgICJub3QgY2hlYXAiLAogICAgICAgICAgICAgICAgICAgICAibm8gcmVncmV0cyIKICAgICAgICAgICAgICAgICAgICAgCikKCiMgRmluZCBzeW5vbnltcyBmb3IgdGhlIHBocmFzZXMgYWJvdmUgdG8gcmVwbGFjZQpzeW5vbnltcyA8LSBjKCJleHBlbnNpdmUiLAogICAgICAgICAgICAgICJmdW5jdGlvbmFsIiwKICAgICAgICAgICAgICAiY29vbCIsCiAgICAgICAgICAgICAgInNhdGlzZmllZCIsCiAgICAgICAgICAgICAgInNhdGlzZmllZCIsCiAgICAgICAgICAgICAgInNhdGlzZmllZCIsCiAgICAgICAgICAgICAgImV4cGVuc2l2ZSIsCiAgICAgICAgICAgICAgInNhdGlzZmllZCIKKQpsaWJyYXJ5KHRleHRjbGVhbikKIyBSZXBsYWNlIHRoZSBuZWdhdGlvbnMgd2l0aCB0aGVpciBzeW5vbnltcy4Kc2Ftc3VuZy5yZXZpZXdzLnRleHQgPC0gbWdzdWIoc2Ftc3VuZy5yZXZpZXdzLnRleHQkcmV2aWV3X3RleHQsIG5lZ2F0ZWQucGhyYXNlcywgc3lub255bXMpICU+JQogIGRwbHlyOjphc19kYXRhX2ZyYW1lKCkgJT4lCiAgcmVuYW1lKHJldmlld190ZXh0ID0gdmFsdWUpCgpzYW1zdW5nLnJldmlld3MudGV4dAoKYGBgCgpgYGB7cn0Kc2hpZnRlZC53b3JkcyA8LSBpcGhvbmUucmV2aWV3cy50ZXh0ICU+JQogIHVubmVzdF90b2tlbnMoYmlncmFtLCByZXZpZXdfdGV4dCwgdG9rZW4gPSAibmdyYW1zIiwgbiA9IDIpJT4lCiAgZHBseXI6OmNvdW50KGJpZ3JhbSwgc29ydCA9IFRSVUUpICU+JQogIHNlcGFyYXRlKGJpZ3JhbSwgYygid29yZDEiLCAid29yZDIiKSwgc2VwID0gIiAiKSU+JQogIGZpbHRlcih3b3JkMSAlaW4lIG5lZ2F0aW9uLndvcmRzICYgIXdvcmQyICVpbiUgc3RvcF93b3JkcyR3b3JkKSU+JQogIGlubmVyX2pvaW4oZ2V0X3NlbnRpbWVudHMoImJpbmciKSwgYnkgPSBjKHdvcmQyID0gIndvcmQiKSklPiUKICBtdXRhdGUoc2VudGltZW50ID0gaWZlbHNlKHNlbnRpbWVudCA9PSAicG9zaXRpdmUiLCAxLCAtMSkpICU+JQogIG11dGF0ZShzY29yZSA9IHNlbnRpbWVudCAqIG4pICU+JQogIG11dGF0ZSh3b3JkMiA9IHJlb3JkZXIod29yZDIsIHNjb3JlKSkKCnNoaWZ0ZWQud29yZHMKCmlwaG9uZS5yZXZpZXdzLnRleHQgPC0gbWdzdWIoaXBob25lLnJldmlld3MudGV4dCRyZXZpZXdfdGV4dCwgbmVnYXRlZC5waHJhc2VzLCBzeW5vbnltcykgJT4lCiAgZHBseXI6OmFzX2RhdGFfZnJhbWUoKSAlPiUKICByZW5hbWUocmV2aWV3X3RleHQgPSB2YWx1ZSkKCmlwaG9uZS5yZXZpZXdzLnRleHQKYGBgCgojIyBXb3JkY2xvdWQKCmBgYHtyIFNhbXN1bmcgV29yZGNsb3VkIEFtYXpvbiwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KIyBpZiB5b3Ugd2FudCB0byBpZ25vcmUgd29yZHMgdGhhdCBhcmUgZnJlcXVlbnQgYnV0IGRvZXNuJ3QgaGVscCwgYWRkIHRoZW0gdG8gdGhpcyBsaXN0LiAjIyNJZ25vcmUgdGhlIHdvcmRzCmlnbm9yZS53b3JkcyA8LSBkYXRhX2ZyYW1lKHdvcmQgPSBjKCAic2Ftc3VuZyIsInBob25lIikpCgojIGNyZWF0ZSB0aGUgd29yZHMgZnJlcSB0YWJsZQp3b3JkLmZyZXEudGFibGVfcyA8LSBzYW1zdW5nLnJldmlld3MudGV4dCAlPiUgCiAgdW5uZXN0X3Rva2Vucyh3b3JkLCByZXZpZXdfdGV4dCkgJT4lCiAgYW50aV9qb2luKHN0b3Bfd29yZHMpICU+JQogIGFudGlfam9pbihpZ25vcmUud29yZHMpICU+JQogIGRwbHlyOjpjb3VudCh3b3JkLCBzb3J0ID0gVFJVRSkKd29yZC5mcmVxLnRhYmxlX3MKCiMgUGxvdHRpbmcgYSBXb3JkY2xvdWQKd29yZC5mcmVxLnRhYmxlX3MgJT4lIAogIGZpbHRlcihuPjgpICU+JQogIHdpdGgod29yZGNsb3VkKHdvcmQsIG4sCiAgICAgICAgICAgICAgICAgc2NhbGUgPSBjKDUsMC4zKSwKICAgICAgICAgICAgICAgICBjb2xvcnMgPSBicmV3ZXIucGFsKDgsICJEYXJrMiIpKSkKCmBgYAoKYGBge3IgV29yZGNsb3VkIEFwcGxlIEFtYXpvbiwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KIyBpZiB5b3Ugd2FudCB0byBpZ25vcmUgd29yZHMgdGhhdCBhcmUgZnJlcXVlbnQgYnV0IGRvZXNuJ3QgaGVscCwgYWRkIHRoZW0gdG8gdGhpcyBsaXN0LiAjIyNJZ25vcmUgdGhlIHdvcmRzCmlnbm9yZS53b3JkcyA8LSBkYXRhX2ZyYW1lKHdvcmQgPSBjKCJpcGhvbmUiLCAicGhvbmUiLCJhcHBsZSIsICIxMyIpKQoKIyBjcmVhdGUgdGhlIHdvcmRzIGZyZXEgdGFibGUKd29yZC5mcmVxLnRhYmxlX2E8LSBpcGhvbmUucmV2aWV3cy50ZXh0ICU+JSAKICB1bm5lc3RfdG9rZW5zKHdvcmQsIHJldmlld190ZXh0KSAlPiUKICBhbnRpX2pvaW4oc3RvcF93b3JkcykgJT4lCiAgYW50aV9qb2luKGlnbm9yZS53b3JkcykgJT4lCiAgZHBseXI6OmNvdW50KHdvcmQsIHNvcnQgPSBUUlVFKQp3b3JkLmZyZXEudGFibGVfYQoKIyBQbG90dGluZyBhIFdvcmRjbG91ZAp3b3JkLmZyZXEudGFibGVfYSAlPiUgCiAgZmlsdGVyKG4+OCkgJT4lCiAgd2l0aCh3b3JkY2xvdWQod29yZCwgbiwKICAgICAgICAgICAgICAgICBzY2FsZSA9IGMoNSwwLjMpLAogICAgICAgICAgICAgICAgIGNvbG9ycyA9IGJyZXdlci5wYWwoOCwgIkRhcmsyIikpKQoKYGBgCgojIyBTZW50aW1lbnQgQW5hbHlzaXMKCmBgYHtyIFBvc2l0aXZlIGFuZCBuZWdhdGl2ZSB3b3JkcyBBbWF6b24gU2Ftc3VuZywgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KIyBNb3N0IGNvbW1vbiBQb3NpdGl2ZSBhbmQgTmVnYXRpdmUgd29yZHMgdXNpbmcgQmluZwpzYW1zdW5nLnJldmlld3MudGV4dCAlPiUgCiAgdW5uZXN0X3Rva2Vucyh3b3JkLCByZXZpZXdfdGV4dCkgJT4lCiAgYW50aV9qb2luKHN0b3Bfd29yZHMpICU+JQogIGFudGlfam9pbihpZ25vcmUud29yZHMpICU+JQogIGlubmVyX2pvaW4oZ2V0X3NlbnRpbWVudHMoImJpbmciKSkgJT4lCiAgZHBseXI6OmNvdW50KHdvcmQsIHNlbnRpbWVudCwgc29ydCA9IFRSVUUpICU+JQogIGZpbHRlcihuID4gMikgJT4lCiAgbXV0YXRlKHdvcmQgPSByZW9yZGVyKHdvcmQsIG4pKSAlPiUKICBtdXRhdGUocGVyY2VudCA9IHJvdW5kKG4vc3VtKG4pLCAzKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gd29yZCwgeSA9IHBlcmNlbnQsIGZpbGwgPSBzZW50aW1lbnQsIGxhYmVsID0gcGVyY2VudCkpICsKICBnZW9tX2NvbChzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgZmFjZXRfd3JhcCh+c2VudGltZW50LCBzY2FsZXMgPSAiZnJlZV95IikgKwogIGdlb21fdGV4dChhZXMoeSA9IDAuNypwZXJjZW50KSkgKwogIGxhYnModGl0bGUgPSAiU2Ftc3VuZyBQb2xhcml0eSAoYmluZykiKSArCiAgY29vcmRfZmxpcCgpICsgCiAgdGhlbWVfYncoKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCgpgYGAKCmBgYHtyIFBvc2l0aXZlIGFuZCBuZWdhdGl2ZSB3b3JkcyBBbWF6b24gQXBwbGUsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiMgTW9zdCBjb21tb24gUG9zaXRpdmUgYW5kIE5lZ2F0aXZlIHdvcmRzIHVzaW5nIEJpbmcKaXBob25lLnJldmlld3MudGV4dCAlPiUgCiAgdW5uZXN0X3Rva2Vucyh3b3JkLCByZXZpZXdfdGV4dCkgJT4lCiAgYW50aV9qb2luKHN0b3Bfd29yZHMpICU+JQogIGFudGlfam9pbihpZ25vcmUud29yZHMpICU+JQogIGlubmVyX2pvaW4oZ2V0X3NlbnRpbWVudHMoImJpbmciKSkgJT4lCiAgZHBseXI6OmNvdW50KHdvcmQsIHNlbnRpbWVudCwgc29ydCA9IFRSVUUpICU+JQogIGZpbHRlcihuID4gMikgJT4lCiAgbXV0YXRlKHdvcmQgPSByZW9yZGVyKHdvcmQsIG4pKSAlPiUKICBtdXRhdGUocGVyY2VudCA9IHJvdW5kKG4vc3VtKG4pLCAzKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gd29yZCwgeSA9IHBlcmNlbnQsIGZpbGwgPSBzZW50aW1lbnQsIGxhYmVsID0gcGVyY2VudCkpICsKICBnZW9tX2NvbChzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgZmFjZXRfd3JhcCh+c2VudGltZW50LCBzY2FsZXMgPSAiZnJlZV95IikgKwogIGdlb21fdGV4dChhZXMoeSA9IDAuNypwZXJjZW50KSkgKwogIGxhYnModGl0bGUgPSAiaVBob25lIDEzIFdvcmQgUG9sYXJpdHkgKGJpbmcpIikgKwogIGNvb3JkX2ZsaXAoKSArIAogIHRoZW1lX2J3KCkgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQoKYGBgCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojIEJpbmcgU2Ftc3VuZwpiaW5nLm1lYW4uc2NvcmVfcyA8LSB3b3JkLmZyZXEudGFibGVfcyAlPiUgCiAgaW5uZXJfam9pbihnZXRfc2VudGltZW50cygiYmluZyIpKSAlPiUKICBtdXRhdGUoc2VudGltZW50ID0gaWZlbHNlKHNlbnRpbWVudCA9PSAicG9zaXRpdmUiLCAxLCAtMSkpICU+JQogIHN1bW1hcmlzZShTYW1zdW5nX21lYW4gPSBtZWFuKHNlbnRpbWVudCkpCgpiaW5nLm1lYW4uc2NvcmVfYSA8LSB3b3JkLmZyZXEudGFibGVfYSAlPiUgCiAgaW5uZXJfam9pbihnZXRfc2VudGltZW50cygiYmluZyIpKSAlPiUKICBtdXRhdGUoc2VudGltZW50ID0gaWZlbHNlKHNlbnRpbWVudCA9PSAicG9zaXRpdmUiLCAxLCAtMSkpICU+JQogIHN1bW1hcmlzZShBcHBsZV9tZWFuID0gbWVhbihzZW50aW1lbnQpKQoKZGF0YS5mcmFtZShiaW5nLm1lYW4uc2NvcmVfcywgYmluZy5tZWFuLnNjb3JlX2EpCgpgYGAKCmBgYHtyfQojU2Ftc3VuZwojIHJlc2NhbGUgdGhlIHJhbmdlIHRvIDUgc3RhciByYW5nZS4KYmluZy5tZWFuLnNjb3JlX3M8LXJlc2NhbGUoYmluZy5tZWFuLnNjb3JlX3MkbWVhbiwgdG8gPSBjKDEsNSksIGZyb20gPSBjKC0xLDEpKQoKIyBBZmlubiBzY29yZXMgYXJlIGZyb20gLTUgdG8gNS4KYWZpbm4ubWVhbi5zY29yZV9zIDwtIHdvcmQuZnJlcS50YWJsZV9zICU+JSAKICBpbm5lcl9qb2luKGdldF9zZW50aW1lbnRzKCJhZmlubiIpKSU+JQogIHN1bW1hcmlzZShTYW1zdW5nX21lYW4gPSBtZWFuKHZhbHVlKSkKCiMgcmVzY2FsZSB0aGUgcmFuZ2UgdG8gNSBzdGFyIHJhbmdlLgphZmlubi5tZWFuLnNjb3JlX3M8LXJlc2NhbGUoYWZpbm4ubWVhbi5zY29yZV9zJFNhbXN1bmdfbWVhbiwgdG8gPSBjKDEsNSksIGZyb20gPSBjKC01LDUpKQoKI0FwcGxlCiMgcmVzY2FsZSB0aGUgcmFuZ2UgdG8gNSBzdGFyIHJhbmdlLgpiaW5nLm1lYW4uc2NvcmVfYTwtcmVzY2FsZShiaW5nLm1lYW4uc2NvcmVfYSRtZWFuLCB0byA9IGMoMSw1KSwgZnJvbSA9IGMoLTEsMSkpCgojIEFmaW5uIHNjb3JlcyBhcmUgZnJvbSAtNSB0byA1LgphZmlubi5tZWFuLnNjb3JlX2EgPC0gd29yZC5mcmVxLnRhYmxlX2EgJT4lIAogIGlubmVyX2pvaW4oZ2V0X3NlbnRpbWVudHMoImFmaW5uIikpJT4lCiAgc3VtbWFyaXNlKEFwcGxlX21lYW4gPSBtZWFuKHZhbHVlKSkKCiMgcmVzY2FsZSB0aGUgcmFuZ2UgdG8gNSBzdGFyIHJhbmdlLgphZmlubi5tZWFuLnNjb3JlX2E8LXJlc2NhbGUoYWZpbm4ubWVhbi5zY29yZV9hJEFwcGxlX21lYW4sIHRvID0gYygxLDUpLCBmcm9tID0gYygtNSw1KSkKYWZpbm4ubWVhbi5zY29yZV9hCgpkYXRhLnRhYmxlKGFmaW5uLm1lYW4uc2NvcmVfcywgYWZpbm4ubWVhbi5zY29yZV9hKQpgYGAKCiMjIFdvcmQgQ29ycmVsYXRpb24KCmBgYHtyfQojIENvcnJlbGF0aW9uIFRlcm1zCiMgVGhlIGNvcnJlbGF0aW9uIG9mIGFwcGVhcmluZyB0b2dldGhlciBpbiBhIHJldmlldwpzYW1zdW5nLmNvcnJlbGF0aW9uLnRlcm1zIDwtIHNhbXN1bmcucmV2aWV3cy50ZXh0ICU+JQogIG11dGF0ZShyZXZpZXcgPSByb3dfbnVtYmVyKCkpICU+JQogIHVubmVzdF90b2tlbnMod29yZCwgcmV2aWV3X3RleHQpICU+JQogIGZpbHRlcighd29yZCAlaW4lIHN0b3Bfd29yZHMkd29yZCkgJT4lCiAgZ3JvdXBfYnkod29yZCkgJT4lCiAgZmlsdGVyKG4oKSA+PTcpJT4lCiAgcGFpcndpc2VfY29yKHdvcmQsIHJldmlldywgc29ydCA9IFRSVUUpCnNhbXN1bmcuY29ycmVsYXRpb24udGVybXMKCmxpYnJhcnkoZ2dyYXBoKQpsaWJyYXJ5KGlncmFwaCkKc2Ftc3VuZy5jb3JyZWxhdGlvbi50ZXJtcyAlPiUKICBmaWx0ZXIoY29ycmVsYXRpb24gPj0gMC41MCkgJT4lCiAgZ3JhcGhfZnJvbV9kYXRhX2ZyYW1lKCkgJT4lCiAgZ2dyYXBoKGxheW91dCA9ICJpZ3JhcGgiLCBhbGdvcml0aG0gPSAia2siKSArCiAgZ2VvbV9lZGdlX2xpbmsoYWVzKGFscGhhID0gY29ycmVsYXRpb24pLCAKICAgICAgICAgICAgICAgICBzaG93LmxlZ2VuZCA9IEZBTFNFKSsKICBnZW9tX25vZGVfcG9pbnQoY29sb3IgPSAibGlnaHRibHVlIiwgc2l6ZSA9IDIpICsKICBnZW9tX25vZGVfdGV4dChhZXMobGFiZWwgPSBuYW1lKSwgcmVwZWwgPSBUUlVFKSArCiAgdGhlbWVfdm9pZCgpKwogIGdndGl0bGUoIkNvcnJlbGF0aW9uIG9mIHRlcm1zIGluIFNhbXN1bmcgUzIyIFJldmlld3MiKQpgYGAKCmBgYHtyfQojIENvcnJlbGF0aW9uIFRlcm1zCiMgVGhlIGNvcnJlbGF0aW9uIG9mIGFwcGVhcmluZyB0b2dldGhlciBpbiBhIHJldmlldwphcHBsZS5jb3JyZWxhdGlvbi50ZXJtcyA8LSBpcGhvbmUucmV2aWV3cy50ZXh0ICU+JQogIG11dGF0ZShyZXZpZXcgPSByb3dfbnVtYmVyKCkpICU+JQogIHVubmVzdF90b2tlbnMod29yZCwgcmV2aWV3X3RleHQpICU+JQogIGZpbHRlcighd29yZCAlaW4lIHN0b3Bfd29yZHMkd29yZCkgJT4lCiAgZ3JvdXBfYnkod29yZCkgJT4lCiAgZmlsdGVyKG4oKSA+PSA1KSU+JQogIHBhaXJ3aXNlX2Nvcih3b3JkLCByZXZpZXcsIHNvcnQgPSBUUlVFKQphcHBsZS5jb3JyZWxhdGlvbi50ZXJtcwoKbGlicmFyeShnZ3JhcGgpCmxpYnJhcnkoaWdyYXBoKQphcHBsZS5jb3JyZWxhdGlvbi50ZXJtcyAlPiUKICBmaWx0ZXIoY29ycmVsYXRpb24gPj0gMC41MCkgJT4lCiAgZ3JhcGhfZnJvbV9kYXRhX2ZyYW1lKCkgJT4lCiAgZ2dyYXBoKGxheW91dCA9ICJpZ3JhcGgiLCBhbGdvcml0aG0gPSAia2siKSArCiAgZ2VvbV9lZGdlX2xpbmsoYWVzKGFscGhhID0gY29ycmVsYXRpb24pLCAKICAgICAgICAgICAgICAgICBzaG93LmxlZ2VuZCA9IEZBTFNFKSsKICBnZW9tX25vZGVfcG9pbnQoY29sb3IgPSAibGlnaHRibHVlIiwgc2l6ZSA9IDIpICsKICBnZW9tX25vZGVfdGV4dChhZXMobGFiZWwgPSBuYW1lKSwgcmVwZWwgPSBUUlVFKSArCiAgdGhlbWVfdm9pZCgpKwogIGdndGl0bGUoIkNvcnJlbGF0aW9uIG9mIHRlcm1zIGluIEFwcGxlIGlQaG9uZSAxMyBSZXZpZXdzIikKCmBgYAoKYGBge3J9CmJpZ3JhbXMubmV0d29yay5kZl9zIDwtIHNhbXN1bmcucmV2aWV3cy50ZXh0ICU+JQogIHVubmVzdF90b2tlbnMoYmlncmFtLCByZXZpZXdfdGV4dCwgdG9rZW4gPSAibmdyYW1zIiwgbiA9IDIpICU+JQogIHNlcGFyYXRlKGJpZ3JhbSwgYygid29yZDEiLCAid29yZDIiKSwgc2VwID0gIiAiKSAlPiUKICBmaWx0ZXIoIXdvcmQxICVpbiUgc3RvcF93b3JkcyR3b3JkICYgIXdvcmQyICVpbiUgc3RvcF93b3JkcyR3b3JkKSAlPiUKICBkcGx5cjo6Y291bnQod29yZDEsIHdvcmQyLCBzb3J0ID0gVFJVRSkgJT4lCiAgZmlsdGVyKG4gPiA1KQoKYmlncmFtcy5uZXR3b3JrX3MgPC0gZ3JhcGhfZnJvbV9kYXRhX2ZyYW1lKGJpZ3JhbXMubmV0d29yay5kZl9zKQpiaWdyYW1zLm5ldHdvcmtfcwoKYmlncmFtcy5uZXR3b3JrLmRmX2EgPC1pcGhvbmUucmV2aWV3cy50ZXh0ICU+JQogIHVubmVzdF90b2tlbnMoYmlncmFtLCByZXZpZXdfdGV4dCwgdG9rZW4gPSAibmdyYW1zIiwgbiA9IDIpICU+JQogIHNlcGFyYXRlKGJpZ3JhbSwgYygid29yZDEiLCAid29yZDIiKSwgc2VwID0gIiAiKSAlPiUKICBmaWx0ZXIoIXdvcmQxICVpbiUgc3RvcF93b3JkcyR3b3JkICYgIXdvcmQyICVpbiUgc3RvcF93b3JkcyR3b3JkKSAlPiUKICBkcGx5cjo6Y291bnQod29yZDEsIHdvcmQyLCBzb3J0ID0gVFJVRSkgJT4lCiAgZmlsdGVyKG4gPiAyKQoKYmlncmFtcy5uZXR3b3JrX2EgPC0gZ3JhcGhfZnJvbV9kYXRhX2ZyYW1lKGJpZ3JhbXMubmV0d29yay5kZl9hKQpiaWdyYW1zLm5ldHdvcmtfYQpgYGAKCmBgYHtyfQojIG5vdyB3ZSBmaW5kIHRoZSBjZW50cmFsaXR5IG1lYXN1cmVzIG9mIHRoZSBuZXR3b3JrCiMgZGVncmVlOnRoZSBudW1iZXIgb2YgaXRzIGFkamFjZW50IGVkZ2VzIChtZWFzdXJlIG9mIGRpcmVjdCBpbmZsdWVuY2UpCmRlZ19zIDwtIGRlZ3JlZShiaWdyYW1zLm5ldHdvcmtfcywgbW9kZSA9ICJhbGwiKQoKI0stY29yZSBkZWNvbXBvc2l0aW9uIGFsbG93cyB1cyB0byBpZGVudGlmeSB0aGUgY29yZSBhbmQgdGhlIHBlcmlwaGVyeSBvZiB0aGUgbmV0d29yay4gQSBrLWNvcmUgaXMgYSBtYXhpbWFsIHN1Ym5ldCBvZiBhIG5ldHdvcmsgc3VjaCB0aGF0IGFsbCBub2RlcyBoYXZlIGF0IGxlYXN0IGRlZ3JlZSBLLgpjb3JlX3MgPC0gY29yZW5lc3MoYmlncmFtcy5uZXR3b3JrX3MsIG1vZGUgPSAiYWxsIikKCiMgYmV0d2Vlbm5lc3MgbWVhc3VyZXMgYnJva2VyYWdlIG9yIGdhdGVrZWVwaW5nIHBvdGVudGlhbC4gSXQgaXMgKGFwcHJveGltYXRlbHkpIHRoZSBudW1iZXIgb2Ygc2hvcnRlc3QgcGF0aHMgYmV0d2VlbiBub2RlcyB0aGF0IHBhc3MgdGhyb3VnaCBhIHBhcnRpY3VsYXIgbm9kZS4KYmV0d19zIDwtIGJldHdlZW5uZXNzKGJpZ3JhbXMubmV0d29ya19zKQoKI0VpZ2VudmVjdG9yIGNlbnRyYWxpdHkgaXMgYSBtZWFzdXJlIG9mIGJlaW5nIHdlbGwtY29ubmVjdGVkIGNvbm5lY3RlZCB0byB0aGUgd2VsbC1jb25uZWN0ZWQuIEZpcnN0IGVpZ2VudmVjdG9yIG9mIHRoZSBncmFwaCBhZGphY2VuY3kgbWF0cml4LiBPbmx5IHdvcmtzIHdpdGggdW5kaXJlY3RlZCBuZXR3b3Jrcy4KZWlnZW5fcyA8LSBlaWdlbl9jZW50cmFsaXR5KGJpZ3JhbXMubmV0d29ya19zLCBkaXJlY3RlZCA9IFRSVUUpCm1lbWJlcnNfcyA8LSBjbHVzdGVyX3dhbGt0cmFwKGJpZ3JhbXMubmV0d29ya19zKQoKbGlicmFyeShpZ3JhcGgpCmJpZ3JhbXMubmV0d29ya19zIDwtIHNpbXBsaWZ5KGJpZ3JhbXMubmV0d29ya19zCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAjcmVtb3ZlLm11bHRpcGxlID0gRkFMU0UsICNlcnJvciBvY2N1cmVkID8KICAgICAgICAgICAgICAgICAgICAgICAgICAgICNyZW1vdmUubG9vcHMgPSBUUlVFKQopClYoYmlncmFtcy5uZXR3b3JrX3MpJGNvbG9yIDwtIG1lbWJlcnMkbWVtYmVyc2hpcCsxCgpgYGAKCmBgYHtyfQojIG5vdyB3ZSBmaW5kIHRoZSBjZW50cmFsaXR5IG1lYXN1cmVzIG9mIHRoZSBuZXR3b3JrCiMgZGVncmVlOnRoZSBudW1iZXIgb2YgaXRzIGFkamFjZW50IGVkZ2VzIChtZWFzdXJlIG9mIGRpcmVjdCBpbmZsdWVuY2UpCmRlZ19zIDwtIGRlZ3JlZShiaWdyYW1zLm5ldHdvcmtfcywgbW9kZSA9ICJhbGwiKQoKI0stY29yZSBkZWNvbXBvc2l0aW9uIGFsbG93cyB1cyB0byBpZGVudGlmeSB0aGUgY29yZSBhbmQgdGhlIHBlcmlwaGVyeSBvZiB0aGUgbmV0d29yay4gQSBrLWNvcmUgaXMgYSBtYXhpbWFsIHN1Ym5ldCBvZiBhIG5ldHdvcmsgc3VjaCB0aGF0IGFsbCBub2RlcyBoYXZlIGF0IGxlYXN0IGRlZ3JlZSBLLgpjb3JlX3MgPC0gY29yZW5lc3MoYmlncmFtcy5uZXR3b3JrX3MsIG1vZGUgPSAiYWxsIikKCiMgYmV0d2Vlbm5lc3MgbWVhc3VyZXMgYnJva2VyYWdlIG9yIGdhdGVrZWVwaW5nIHBvdGVudGlhbC4gSXQgaXMgKGFwcHJveGltYXRlbHkpIHRoZSBudW1iZXIgb2Ygc2hvcnRlc3QgcGF0aHMgYmV0d2VlbiBub2RlcyB0aGF0IHBhc3MgdGhyb3VnaCBhIHBhcnRpY3VsYXIgbm9kZS4KYmV0d19zIDwtIGJldHdlZW5uZXNzKGJpZ3JhbXMubmV0d29ya19zKQoKI0VpZ2VudmVjdG9yIGNlbnRyYWxpdHkgaXMgYSBtZWFzdXJlIG9mIGJlaW5nIHdlbGwtY29ubmVjdGVkIGNvbm5lY3RlZCB0byB0aGUgd2VsbC1jb25uZWN0ZWQuIEZpcnN0IGVpZ2VudmVjdG9yIG9mIHRoZSBncmFwaCBhZGphY2VuY3kgbWF0cml4LiBPbmx5IHdvcmtzIHdpdGggdW5kaXJlY3RlZCBuZXR3b3Jrcy4KZWlnZW5fcyA8LSBlaWdlbl9jZW50cmFsaXR5KGJpZ3JhbXMubmV0d29ya19zLCBkaXJlY3RlZCA9IFRSVUUpCm1lbWJlcnNfcyA8LSBjbHVzdGVyX3dhbGt0cmFwKGJpZ3JhbXMubmV0d29ya19zKQoKbGlicmFyeShpZ3JhcGgpCmJpZ3JhbXMubmV0d29ya19zIDwtIHNpbXBsaWZ5KGJpZ3JhbXMubmV0d29ya19zCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAjcmVtb3ZlLm11bHRpcGxlID0gRkFMU0UsICNlcnJvciBvY2N1cmVkID8KICAgICAgICAgICAgICAgICAgICAgICAgICAgICNyZW1vdmUubG9vcHMgPSBUUlVFKQopClYoYmlncmFtcy5uZXR3b3JrX3MpJGNvbG9yIDwtIG1lbWJlcnNfcyRtZW1iZXJzaGlwKzEKCiMgVXNpbmcgIkNvcmVuZXNzIiBhcyBzaXplCiMgQ29yZW5lc3MgLT4gbWVhbiAoYXZlcmFnZSBkaXN0YW5jZSB0byBhbGwgdGhlIG90aGVyIG5vZGVzLCBkaWZmdXNpb24gb2YgaW5mb3JtYXRpb24pCnBsb3QoYmlncmFtcy5uZXR3b3JrX3MsCiAgICAgbGF5b3V0ID0gbGF5b3V0X3dpdGhfZnIsCiAgICAgdmVydGV4LmxhYmVsLmNvbG9yID0gImJsYWNrIiwKICAgICB2ZXJ0ZXgubGFiZWwuY2V4ID0gMC45LAogICAgIHZlcnRleC5sYWJlbC5kaXN0ID0gMCwKICAgICB2ZXJ0ZXguZnJhbWUuY29sb3IgPSAwLAogICAgIHZlcnRleC5zaXplID0gY29yZV9zKjEwLCAKICAgICBlZGdlLmFycm93LnNpemUgPSAwLjAxLAogICAgIGVkZ2UuY3VydmVkID0gMC43LAogICAgIGVkZ2UuY29sb3IgPSAiZ3JheSIsCiAgICAgbWFpbiA9ICJCaWdyYW0gQ29tbXVuaXRpZXMgKFNhbXN1bmcpIgopCm10ZXh0KCJDb3JlbmVzcyIpCgojIFVzaW5nICJEZWdyZWUiIGFzIHNpemUKIyBkZWdyZWU9bW9kZSAobnVtYmVyIG9mIGVkZ2VzIG9mIHRoZSBub2RlLCBpbi1kZWdyZWU6cHJlc3RpZ2UKCnBsb3QoYmlncmFtcy5uZXR3b3JrX3MsCiAgICAgbGF5b3V0ID0gbGF5b3V0X3dpdGhfZnIsCiAgICAgdmVydGV4LmxhYmVsLmNvbG9yID0gImJsYWNrIiwKICAgICB2ZXJ0ZXgubGFiZWwuY2V4ID0gMC45LAogICAgIHZlcnRleC5sYWJlbC5kaXN0ID0gMCwKICAgICB2ZXJ0ZXguZnJhbWUuY29sb3IgPSAwLAogICAgIHZlcnRleC5zaXplID0gZGVnX3MsIAogICAgIGVkZ2UuYXJyb3cuc2l6ZSA9IDAuMDEsCiAgICAgZWRnZS5jdXJ2ZWQgPSAwLjcsCiAgICAgZWRnZS5jb2xvciA9ICJncmF5IiwKICAgICBtYWluID0gIkJpZ3JhbSBDb21tdW5pdGllcyAoU2Ftc3VuZykiCikKbXRleHQoIkRlZ3JlZSIpCgojIFVzaW5nICJFaWdlbnZlY3RvciBDZW50cmFsaXR5IiBhcyBzaXplCiMgY2VudHJhbGl0eSAodGhlIG1vc3QgY29ubmVjdGVkIHdvcmRzKQpwbG90KGJpZ3JhbXMubmV0d29ya19zLAogICAgIGxheW91dCA9IGxheW91dF93aXRoX2ZyLAogICAgIHZlcnRleC5sYWJlbC5jb2xvciA9ICJibGFjayIsCiAgICAgdmVydGV4LmxhYmVsLmNleCA9IDAuOCwKICAgICB2ZXJ0ZXgubGFiZWwuZGlzdCA9IDAsCiAgICAgdmVydGV4LnNpemUgPSBlaWdlbl9zJHZlY3RvcioyMCwgCiAgICAgZWRnZS5hcnJvdy5zaXplID0gMC4wMSwKICAgICBlZGdlLmN1cnZlZCA9IDAuNywKICAgICBlZGdlLmNvbG9yID0gImJsYWNrIiwKICAgICBtYWluID0gIkJpZ3JhbSBDb21tdW5pdGllcyAoU2Ftc3VuZykiCikKbXRleHQoIkVpZ2VudmVjdG9yIENlbnRyYWxpdHkiKQoKIyBVc2luZyAiQmV0d2Vlbm5lc3MiIGFzIHNpemUKI0JldHdlZW5uZXNzIC0+IG1lZGlhbiAod2VpZ2h0ZWQgIyBvZiBwYXRocyBnb2luZyB0aHJvdWdoIHRoZSBub2RlKQpwbG90KGJpZ3JhbXMubmV0d29ya19zLAogICAgIGxheW91dCA9IGxheW91dF93aXRoX2ZyLAogICAgIHZlcnRleC5sYWJlbC5jb2xvciA9ICJibGFjayIsCiAgICAgdmVydGV4LmxhYmVsLmNleCA9IDAuOCwKICAgICB2ZXJ0ZXgubGFiZWwuZGlzdCA9IDAsCiAgICAgdmVydGV4LnNpemUgPSBiZXR3X3MsIAogICAgIGVkZ2UuYXJyb3cuc2l6ZSA9IDAuMDEsCiAgICAgZWRnZS5jdXJ2ZWQgPSAwLjcsCiAgICAgZWRnZS5jb2xvciA9ICJsaWdodGdyZXkiLAogICAgIG1haW4gPSAiQmlncmFtIENvbW11bml0aWVzIChTYW1zdW5nKSIKKQptdGV4dCgiQmV0d2Vlbm5lc3MiKQoKYGBgCgpgYGB7ciBOZXR3b3JrIGZvciBBcHBsZSwgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojIG5vdyB3ZSBmaW5kIHRoZSBjZW50cmFsaXR5IG1lYXN1cmVzIG9mIHRoZSBuZXR3b3JrCiMgZGVncmVlOnRoZSBudW1iZXIgb2YgaXRzIGFkamFjZW50IGVkZ2VzIChtZWFzdXJlIG9mIGRpcmVjdCBpbmZsdWVuY2UpCmRlZ19hIDwtIGRlZ3JlZShiaWdyYW1zLm5ldHdvcmtfYSwgbW9kZSA9ICJhbGwiKQoKI0stY29yZSBkZWNvbXBvc2l0aW9uIGFsbG93cyB1cyB0byBpZGVudGlmeSB0aGUgY29yZSBhbmQgdGhlIHBlcmlwaGVyeSBvZiB0aGUgbmV0d29yay4gQSBrLWNvcmUgaXMgYSBtYXhpbWFsIHN1Ym5ldCBvZiBhIG5ldHdvcmsgc3VjaCB0aGF0IGFsbCBub2RlcyBoYXZlIGF0IGxlYXN0IGRlZ3JlZSBLLgpjb3JlX2EgPC0gY29yZW5lc3MoYmlncmFtcy5uZXR3b3JrX2EsIG1vZGUgPSAiYWxsIikKCiMgYmV0d2Vlbm5lc3MgbWVhc3VyZXMgYnJva2VyYWdlIG9yIGdhdGVrZWVwaW5nIHBvdGVudGlhbC4gSXQgaXMgKGFwcHJveGltYXRlbHkpIHRoZSBudW1iZXIgb2Ygc2hvcnRlc3QgcGF0aHMgYmV0d2VlbiBub2RlcyB0aGF0IHBhc3MgdGhyb3VnaCBhIHBhcnRpY3VsYXIgbm9kZS4KYmV0d19hIDwtIGJldHdlZW5uZXNzKGJpZ3JhbXMubmV0d29ya19hKQoKI0VpZ2VudmVjdG9yIGNlbnRyYWxpdHkgaXMgYSBtZWFzdXJlIG9mIGJlaW5nIHdlbGwtY29ubmVjdGVkIGNvbm5lY3RlZCB0byB0aGUgd2VsbC1jb25uZWN0ZWQuIEZpcnN0IGVpZ2VudmVjdG9yIG9mIHRoZSBncmFwaCBhZGphY2VuY3kgbWF0cml4LiBPbmx5IHdvcmtzIHdpdGggdW5kaXJlY3RlZCBuZXR3b3Jrcy4KZWlnZW5fYSA8LSBlaWdlbl9jZW50cmFsaXR5KGJpZ3JhbXMubmV0d29ya19hLCBkaXJlY3RlZCA9IFRSVUUpCm1lbWJlcnNfYSA8LSBjbHVzdGVyX3dhbGt0cmFwKGJpZ3JhbXMubmV0d29ya19hKQoKbGlicmFyeShpZ3JhcGgpCmJpZ3JhbXMubmV0d29ya19hIDwtIHNpbXBsaWZ5KGJpZ3JhbXMubmV0d29ya19hCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAjcmVtb3ZlLm11bHRpcGxlID0gRkFMU0UsICNlcnJvciBvY2N1cmVkID8KICAgICAgICAgICAgICAgICAgICAgICAgICAgICNyZW1vdmUubG9vcHMgPSBUUlVFKQopClYoYmlncmFtcy5uZXR3b3JrX2EpJGNvbG9yIDwtIG1lbWJlcnNfYSRtZW1iZXJzaGlwKzEKCiMgVXNpbmcgIkNvcmVuZXNzIiBhcyBzaXplCiMgQ29yZW5lc3MgLT4gbWVhbiAoYXZlcmFnZSBkaXN0YW5jZSB0byBhbGwgdGhlIG90aGVyIG5vZGVzLCBkaWZmdXNpb24gb2YgaW5mb3JtYXRpb24pCnBsb3QoYmlncmFtcy5uZXR3b3JrX2EsCiAgICAgbGF5b3V0ID0gbGF5b3V0X3dpdGhfZnIsCiAgICAgdmVydGV4LmxhYmVsLmNvbG9yID0gImJsYWNrIiwKICAgICB2ZXJ0ZXgubGFiZWwuY2V4ID0gMC45LAogICAgIHZlcnRleC5sYWJlbC5kaXN0ID0gMCwKICAgICB2ZXJ0ZXguZnJhbWUuY29sb3IgPSAwLAogICAgIHZlcnRleC5zaXplID0gY29yZV9hKjEwLCAKICAgICBlZGdlLmFycm93LnNpemUgPSAwLjAxLAogICAgIGVkZ2UuY3VydmVkID0gMC43LAogICAgIGVkZ2UuY29sb3IgPSAiZ3JheSIsCiAgICAgbWFpbiA9ICJCaWdyYW0gQ29tbXVuaXRpZXMgKGlQaG9uZSAxMykiCikKbXRleHQoIkNvcmVuZXNzIikKCiMgVXNpbmcgIkRlZ3JlZSIgYXMgc2l6ZQojIGRlZ3JlZT1tb2RlIChudW1iZXIgb2YgZWRnZXMgb2YgdGhlIG5vZGUsIGluLWRlZ3JlZTpwcmVzdGlnZQoKcGxvdChiaWdyYW1zLm5ldHdvcmtfYSwKICAgICBsYXlvdXQgPSBsYXlvdXRfd2l0aF9mciwKICAgICB2ZXJ0ZXgubGFiZWwuY29sb3IgPSAiYmxhY2siLAogICAgIHZlcnRleC5sYWJlbC5jZXggPSAwLjksCiAgICAgdmVydGV4LmxhYmVsLmRpc3QgPSAwLAogICAgIHZlcnRleC5mcmFtZS5jb2xvciA9IDAsCiAgICAgdmVydGV4LnNpemUgPSBkZWdfYSwgCiAgICAgZWRnZS5hcnJvdy5zaXplID0gMC4wMSwKICAgICBlZGdlLmN1cnZlZCA9IDAuNywKICAgICBlZGdlLmNvbG9yID0gImdyYXkiLAogICAgIG1haW4gPSAiQmlncmFtIENvbW11bml0aWVzIChpUGhvbmUgMTMpIgopCm10ZXh0KCJEZWdyZWUiKQoKIyBVc2luZyAiRWlnZW52ZWN0b3IgQ2VudHJhbGl0eSIgYXMgc2l6ZQojIGNlbnRyYWxpdHkgKHRoZSBtb3N0IGNvbm5lY3RlZCB3b3JkcykKcGxvdChiaWdyYW1zLm5ldHdvcmtfYSwKICAgICBsYXlvdXQgPSBsYXlvdXRfd2l0aF9mciwKICAgICB2ZXJ0ZXgubGFiZWwuY29sb3IgPSAiYmxhY2siLAogICAgIHZlcnRleC5sYWJlbC5jZXggPSAwLjgsCiAgICAgdmVydGV4LmxhYmVsLmRpc3QgPSAwLAogICAgIHZlcnRleC5zaXplID0gZWlnZW5fYSR2ZWN0b3IqMjAsIAogICAgIGVkZ2UuYXJyb3cuc2l6ZSA9IDAuMDEsCiAgICAgZWRnZS5jdXJ2ZWQgPSAwLjcsCiAgICAgZWRnZS5jb2xvciA9ICJibGFjayIsCiAgICAgbWFpbiA9ICJCaWdyYW0gQ29tbXVuaXRpZXMgKGlQaG9uZSAxMykiCikKbXRleHQoIkVpZ2VudmVjdG9yIENlbnRyYWxpdHkiKQoKIyBVc2luZyAiQmV0d2Vlbm5lc3MiIGFzIHNpemUKI0JldHdlZW5uZXNzIC0+IG1lZGlhbiAod2VpZ2h0ZWQgIyBvZiBwYXRocyBnb2luZyB0aHJvdWdoIHRoZSBub2RlKQpwbG90KGJpZ3JhbXMubmV0d29ya19hLAogICAgIGxheW91dCA9IGxheW91dF93aXRoX2ZyLAogICAgIHZlcnRleC5sYWJlbC5jb2xvciA9ICJibGFjayIsCiAgICAgdmVydGV4LmxhYmVsLmNleCA9IDAuOCwKICAgICB2ZXJ0ZXgubGFiZWwuZGlzdCA9IDAsCiAgICAgdmVydGV4LnNpemUgPSBiZXR3X2EsIAogICAgIGVkZ2UuYXJyb3cuc2l6ZSA9IDAuMDEsCiAgICAgZWRnZS5jdXJ2ZWQgPSAwLjcsCiAgICAgZWRnZS5jb2xvciA9ICJsaWdodGdyZXkiLAogICAgIG1haW4gPSAiQmlncmFtIENvbW11bml0aWVzIChpUGhvbmUgMTMpIgopCm10ZXh0KCJCZXR3ZWVubmVzcyIpCgpgYGAK